写这样的东西很好:
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)
这样的东西,我该怎么做?
答案 0 :(得分:6)
你不能,你也不应该这样做。如果你能做到这一点,那么要知道fmap (+1) (Left 1)
是Left 1
还是Left 2
会更加困难。
Bifunctor
也就是说,你正在寻找的抽象(可以在任何一方映射的东西)存在,并被称为Bifunctor
。然后,根据您是要映射Left
还是Right
,您可以使用first
或second
:
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
而不是被first
和second
打扰,您可以将数据类型包装在Flip
newtype中,具有查找第二个类型变量的仿函数实例的效果。您仍然依赖于Either
是Bifunctor
这一事实,但您可以避免first
和second
:
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