我一直在阅读great good一书,但我与Applicative Functors稍作讨论。
在以下示例中,max
应用于两个Maybe仿函数的内容并返回Just 6
。
max <$> Just 3 <*> Just 6
为什么在以下示例中返回Left "Hello"
而不是Either仿函数的内容:Left "Hello World"
?
(++) <$> Left "Hello" <*> Left " World"
答案 0 :(得分:12)
这是因为Functor
实例(和Applicative
等)中的type参数是第二个类型参数。在
Either a b
a
类型,Left
值不受函数或应用操作的影响,因为它们被视为失败案例或无法访问。
instance Functor (Either a) where
fmap _ (Left x) = Left x
fmap f (Right y) = Right (f y)
使用Right
,
(++) <$> Right "Hello" <*> Right " World"
要连接。
答案 1 :(得分:8)
为了补充Daniel的优秀答案,我想提出几点:
首先,here's应用实例:
instance Applicative (Either e) where
pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r
你可以看到这是'短路' - 一旦它到达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 -- <<== :(
其次,你的例子有点棘手。通常,函数的类型和e
中的Either e
无关。这是<*>
的类型:
(<*>) :: Applicative f => f (a -> b) -> f a -> f b
如果我们进行替换f
- &gt;&gt; Either e
,我们得到:
(<*>) :: Either e (a -> b) -> Either e a -> Either e b
尽管在您的示例中,e
和a
匹配,但通常它们不会匹配,这意味着您无法多态实现应用该函数的Either e
的Applicative实例一个左手的论点。