kis*_*aya 4 haskell functor either
我一直在读"为了好大学而学习你的哈斯克尔!" 而现在我正在使用"The Functor Typeclass"部分.
在这里,他们通过修复第一种类型将Either变为仿函数,如下所示:
instance Functor (Either a) where
fmap f (Right x) = Right (f x)
fmap f (Left x) = Left x
Run Code Online (Sandbox Code Playgroud)
所以我想问一下,我怎样才能将Either变成第一种类型的仿函数(通过修复第二种类型),这样,我得到了fmap的以下定义
fmap f (Left x) = Left (f x)
fmap f (Right x) = Right x
Run Code Online (Sandbox Code Playgroud)
你不能; Either a
可以是一个仿函数因为部分应用Either
有种* -> *
,但你不能从右边做部分应用.
相反,您可能对以下Bifunctor
实例感兴趣Either
:
instance Bifunctor Either where
bimap f _ (Left a) = Left (f a)
bimap _ g (Right b) = Right (g b)
Run Code Online (Sandbox Code Playgroud)
bimap
采用两个函数,一个用于包装的两种类型中的每一种Either
.
> bimap (+1) length (Left 3)
Left 4
> bimap (+1) length (Right "hi")
Right 2
Run Code Online (Sandbox Code Playgroud)
也有first
和second
集中于一个或另一个类型的功能.second
对应于常规fmap
用于Either
; 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
Run Code Online (Sandbox Code Playgroud)
(帽子提示@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)
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)