简体   繁体   English

适用函子和任一个

[英]Applicative Functors and Left from Either

I have been working through the great good book, but I am struggling slightly with Applicative Functors. 我一直在努力通过大良的书,但我与应用型函子稍微挣扎。

In the following example max is applied to the contents of the two Maybe functors and returns Just 6 . 在以下示例中,将max应用于两个Maybe仿函数的内容,并返回Just 6

max <$> Just 3 <*> Just 6

Why in the following example is Left "Hello" returned instead of the contents of the Either functors: Left "Hello World" ? 在下面的示例中,为什么返回Left "Hello"而不是Either函数的内容: Left "Hello World"

(++) <$> Left "Hello" <*> Left " World"

It's because the type parameter in the Functor instance (and Applicative etc.) is the second type parameter. 这是因为Functor实例(和Applicative等)中的type参数是第二个type参数。 In

Either a b

the a type, and the Left values are not affected by functorial or applicative operations, because they are considered failure cases or otherwise inaccessible. a类型,并且Left值不受函数或应用操作的影响,因为它们被认为是失败情况或无法访问。

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

Use Right , 使用Right

(++)  <$> Right "Hello" <*> Right " World"

to get concatenation. 获得串联。

To add to Daniel's excellent answer, there are a couple points I'd like to make: 除了丹尼尔的出色回答外,我想提出几点要点:

First, here's the Applicative instance: 首先, 这是 Applicative实例:

instance Applicative (Either e) where
    pure             =  Right
    Left  e  <*>  _  =  Left e
    Right f  <*>  r  =  fmap f r

You can see that this is 'short-circuiting' -- as soon as it hits a Left , it aborts and returns that Left. 您会看到这是“短路”-击中Left ,它将中止并返回该Left。 You can check this with poor man's strictness analysis: 您可以通过穷人的严格性分析来检查:

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

Second, your example is slightly tricky. 其次,您的示例有些棘手。 In general, the type of the function and the e in Either e are not related. 通常,函数的类型与e中的Either e都不相关。 Here's <*> s type: 这是<*>的类型:

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

If we make the substitution f -->> Either e , we get: 如果我们进行替换f ->> Either e ,我们得到:

(<*>) :: Either e (a -> b) -> Either e a -> Either e b

Although in your example, e and a match, in general they won't, which means you can't polymorphically implement an Applicative instance for Either e which applies the function to a left-hand argument. 尽管在您的示例中, ea匹配项通常不会,但是这意味着您无法为Either e都多态实现一个Applicative实例,该实例将函数应用于左手参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM