如何使 Either 成为第二种类型的函子

How to make Either into a functor in second type

我一直在阅读 "Learn You A Haskell For Great Good!",现在我在阅读 "The Functor Typeclass" 部分。

在这里,他们通过如下固定第一种类型使 Either 成为仿函数:

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

所以我想问一下,我怎样才能使 Either 成为第一种类型的仿函数(通过固定第二种类型),这样,我得到 fmap

的以下定义
fmap f (Left x) = Left (f x)
fmap f (Right x)  = Right x

你不能; Either a 可以是函子,因为 Either 的部分应用具有种类 * -> *,但你不能从右边进行部分应用。

相反,您可能对 EitherBifunctor 实例感兴趣:

instance Bifunctor Either where
    bimap f _ (Left a) = Left (f a)
    bimap _ g (Right b) = Right (g b)

bimap 接受两个函数,每个函数对应 Either.

包装的两种类型
> bimap (+1) length (Left 3)
Left 4
> bimap (+1) length (Right "hi")
Right 2

还有 firstsecond 函数专注于一种或另一种类型。 second对应于Either的正则fmapfirst 是您要查找的函数。

> first (+1) (Left 3)
Left 4
> first (+1) (Right 3)
Right 3
> second (+1) (Left 3)
Left 3
> second (+1) (Right 3)
Right 4

(向@leftaroundabout 致敬)

Control.Arrow 模块提供了 left 功能,它实际上与 second 相同,但具有更具描述性的名称和不同的派生。比较它们的类型:

> :t Data.Bifunctor.second
Data.Bifunctor.second :: Bifunctor p => (b -> c) -> p a b -> p a c
> :t Control.Arrow.left
Control.Arrow.left :: ArrowChoice a => a b c -> a (Either b d) (Either c d)

second 被硬编码为与函数一起工作,并且可以受到 p ~ Either 的限制。 left 被硬编码为与 Either 一起工作,并且可以受到 a ~ (->).

的限制

令人困惑的是,Control.Arrow 提供了一个 second 函数,它类似于元组的 Bifunctor 实例:

> :t Control.Arrow.second
Control.Arrow.second :: Arrow a => a b c -> a (d, b) (d, c)

> Control.Arrow.second (+1) (1,2) == Data.Bifunctor.second (+1) (1,2)
True