应用函数和左边的任何一个

Jim*_*ies 7 haskell functor either applicative

我一直在阅读这本伟大的好书,但我正在与Applicative Functors稍作讨论.

在下面的示例max中应用了两个Maybe functor的内容并返回Just 6.

max <$> Just 3 <*> Just 6
Run Code Online (Sandbox Code Playgroud)

为什么在以下示例中Left "Hello"返回而不是Either仿函数的内容:Left "Hello World"

(++) <$> Left "Hello" <*> Left " World"
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 12

这是因为Functor实例中的类型参数(Applicative等等)是第二个类型参数.在

Either a b
Run Code Online (Sandbox Code Playgroud)

a类型和Left值不受函子或应用性的操作,因为它们被认为是失败的案例或以其他方式不可访问.

instance Functor (Either a) where
    fmap _ (Left x)  = Left x
    fmap f (Right y) = Right (f y)
Run Code Online (Sandbox Code Playgroud)

Right,

(++)  <$> Right "Hello" <*> Right " World"
Run Code Online (Sandbox Code Playgroud)

得到串联.


Mat*_*ick 8

为了增加Daniel的优秀答案,我想提出几点:

首先,这是 Applicative实例:

instance Applicative (Either e) where
    pure             =  Right
    Left  e  <*>  _  =  Left e
    Right f  <*>  r  =  fmap f r
Run Code Online (Sandbox Code Playgroud)

你可以看到这是"短路" - 一旦它命中Left,它就会中止并返回左边.您可以通过穷人的严格性分析来检查:

ghci> (++) <$> Left "Hello" <*> undefined 
Left "Hello"                              -- <<== it's not undefined :) !!

ghci>  (++) <$> Right "Hello" <*> undefined 
*** Exception: Prelude.undefined          -- <<== undefined ... :(

ghci> Left "oops" <*> undefined <*> undefined 
Left "oops"                               -- <<== :)

ghci> Right (++) <*> undefined <*> undefined 
*** Exception: Prelude.undefined          -- <<== :( 
Run Code Online (Sandbox Code Playgroud)

其次,你的例子有点棘手.通常,函数的类型和ein Either e是无关的.这<*>是类型:

(<*>) :: Applicative f => f (a -> b) -> f a -> f b
Run Code Online (Sandbox Code Playgroud)

如果我们进行替换f- >> Either e,我们得到:

(<*>) :: Either e (a -> b) -> Either e a -> Either e b
Run Code Online (Sandbox Code Playgroud)

虽然在你的例子ea匹配中,通常它们不会,这意味着你不能多态地实现一个Applicative实例,Either e它将函数应用于左侧参数.