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)

现在假设我想反转这个,Left 将 f 应用于值:

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

这不编译,我想我需要有类似的东西Functor (Either _ b),我该怎么做?

4

1 回答 1

6

你不能,也不应该。如果你能做到这一点,就很难知道fmap (+1) (Left 1)应该是Left 1还是Left 2.

Bifunctor

也就是说,您正在寻找的抽象(可以在任一侧映射的东西)存在并称为 a Bifunctor。然后,根据您是要映射到Lefts 还是Rights,您使用firstor 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而不被 and 困扰firstsecond您可以将您的数据类型包装在Flipnewtype 中,这具有查找第二个类型变量的仿函数实例的效果。Either您仍然依赖于a的事实Bifunctor,但您避免了firstand 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
于 2017-01-29T03:40:44.977 回答