如何将 Both(二)变成第二种类型的函子



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

在这里,他们通过修复第一种类型将 Or 变成函子,如下所示:

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

所以我想问,我怎样才能将 要么 变成第一种类型的函子(通过修复第二种类型(,这样,我得到了以下 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的常规fmap;first是您正在寻找的功能。

> 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还提供了类似于元组Bifunctor实例的second函数:

> :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

相关内容

最新更新