我曾多次尝试在Haskell中理解Functor和Monad,但我失败了。这次当我到达LYAH的Applicative Functor时,我以为我理解Applicative typeclasses
,但我对于Maybe的应用实例实现有一些疑问:
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> something = fmap f something
对于上面代码段的最后一行,我的理解如下:
(1)Just f
被拨入f (a->b)
的{{1}}类定义中,(<*>) :: f (a -> b) -> f a -> f b
被拨入f
(2)(a->b)
适用于something
。
我的问题来自(2),为什么没有像f a
那样的文字?
在Functor instance implementation for Maybe中,Just something
和fmap f (Just x) = Just (f x)
被Just x
f a
拨给了fmap :: (a -> b) -> f a -> f b
。
为了验证我的理解,我将something
更改为Just something
:
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> (Just something) = fmap f (Just something)
在gchi下,我试过了
Just (+3) <*> Just 9
得到了相同的结果Just 12
,但是当我尝试
Just (++"hahah") <*> Nothing`
我收到了错误
*** Exception: Functor.hs:(88,3)-(89,60): Non-exhaustive patterns in function <*>
我不知道为什么或我错过了什么?
答案 0 :(得分:3)
instance Applicative Maybe where
pure = Just
Nothing <*> _ = Nothing
(Just f) <*> (Just something) = fmap f (Just something)
通过观察模式,我们可以看到什么是错的!第一个将匹配第一个参数为Nothing
的任何内容,但第二个参数只会匹配Just ...
。没有任何内容与Just f
和Nothing
匹配。仅仅因为第一个参数不是Nothing
并不意味着第二个参数必须是_ <*> Nothing = Nothing
。如果你真的想要明确,你可以在最后一行上面写{{1}}。
答案 1 :(得分:3)
(这是我评论的延伸,并没有真正回答这个问题)
这个替代定义更容易理解:
instance Applicative Maybe where
pure = Just
(Just f) <*> (Just x) = Just (f x)
_ <*> _ = Nothing
我认为你陷入了从名称something
解释过多的陷阱。我总是尝试在应用程序的上下文中命名变量f
和x
(准确地说是在<*>
的上下文中),这就是它们的本质,函数和函数应用的值。