我目前正准备参加关于Haskell的期末考试,我正在考虑Monads,我们举了一个例子:
给出List Monad的以下定义:
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
其中(>>=)
和concatMap
的类型为
(>>=) :: [a] -> (a -> [b]) -> [b]
concatMap :: (a -> [b]) -> [a] -> [b]
表达式的结果是什么?
> [1,2,3] >>= \x -> [x..3] >>= \y -> return x
[1, 1, 1, 2, 2, 3] //Answer
这里的答案与我的想法不同,现在我们简要地介绍了Monads,但是根据我的理解(>>=)
被称为bind,可以在上面的表达式中读作“applyMaybe”。在这种情况下,对于绑定的第一部分,我们得到[1,2,3,2,3,3]
,我们继续绑定的第二部分,但return x
被定义为返回x的列表。应该是[1,2,3,2,3,3]
。但是,我可能误解了这个表达方式。任何人都可以解释我的方法的错误做法,我应该如何解决这个问题。谢谢。
答案 0 :(得分:2)
这种情况对于绑定的第一部分我们得到[1,2,3,2,3,3]
正确。
我们继续绑定的第二部分,但是“return x”被定义为返回x的列表。应该是[1,2,3,2,3,3]。
请注意,......
[1,2,3] >>= \x -> [x..3] >>= \y -> return x
... x
由第一个(>>=)
的(lambda)绑定,而不是第二个[1,2,3] >>= (\x -> [x..3] >>= (\y -> return x))
。一些额外的括号可能会更清楚:
\y -> return x
在y
中,绑定到[1,2,3,2,3,3]
的值(即x
的元素)将被忽略,并被绑定到y
的相应值替换(是,生成每个[1, 2, 3] -- [1,2,3]
[1,2,3, 2,3, 3] -- [1,2,3] >>= \x -> [x..3]
[1,1,1, 2,2, 3] -- [1,2,3] >>= \x -> [x..3] >>= \y -> return x
的原始列表的元素。原则上,我们有:
<UI>
<TextStyle Id="White12" FaceName="Tahoma" Size="12" Red="255" Green="255" Blue="255" />
<UIRef Id="WixUI_InstallDir" />
...
</UI>
答案 1 :(得分:1)
首先,让我们清楚这个表达式是如何被解析的:lambdas是语法预示,即他们尽可能多地抓住它们,使用它作为函数结果。所以你在那里解析为
[1,2,3] >>= (\x -> ([x..3] >>= \y -> return x))
内部表达式实际上写得比它应该更复杂。完全不使用y
,而a >>= \_ -> p
只能写为a >> p
。但是有一个更好的替代品:通常,monadic bind a >>= \q -> return (f q)
等同于fmap f a
,所以你的表达式应该真的写成
[1,2,3] >>= (\x -> (fmap (const x) [x..3]))
或
[1,2,3] >>= \x -> map (const x) [x..3]
或
[1,2,3] >>= \x -> replicate (3-x+1) x
此时应该非常清楚结果是什么,因为列表monad中的>>=
只是映射每个元素并连接结果。