2017-01-29 29 views
1

写这样的实例声明工作正常:与类型变量

data Either a b = Left a | Right b 

instance Functor (Either a) where 
    fmap _ (Left x) = Left x 
    fmap f (Right x) = Right (f x) 

现在可以说,我想这个反转,左应用于F到值:

instance Functor (Either a) where 
    fmap _ (Right x) = Right x 
    fmap f (Left x) = Left (f x) 

这并不编译,我想我需要像Functor (Either _ b)这样的东西,我该怎么做?

+1

你不能,至少没有直接。你可以为'Either'做一个'newtype'包装器。 – melpomene

回答

6

你不能,你不应该。如果你能做到这一点,那么知道fmap (+1) (Left 1)应该是Left 1还是Left 2会更困难。

Bifunctor

这就是说,你正在寻找(动作,可以在任何一方被映射到)的抽象存在,被称为Bifunctor。然后,根据您是否想映射在Left S或在Right S,您使用firstsecond

ghci> first (+1) (Left 1) 
Left 2 
ghci> second (+1) (Left 1) 
Left 1 
ghci> first (+1) (Right 1) 
Right 1 
ghci> second (+1) (Right 1) 
Right 2 

Flip

或者,如果你想要,而不是固守fmap被打扰与firstsecond,您可以将您的数据类型包装在Flip新类型中,这会找到第二个类型变量的函子实例。你仍然依赖于一个事实,即EitherBifunctor,但你避免firstsecond

ghci> fmap (+1) (Flip (Left 1)) 
Flip (Left 2) 
ghci> fmap (+1) (Left 1) 
Left 1 
ghci> fmap (+1) (Flip (Right 1)) 
Flip (Right 2) 
ghci> fmap (+1) (Right 1) 
Right 1