我很难理解单子的迭代行为是如何从它的definition导出的。
instance Monad [] where
m >>= f = concatMap f m
return x = [x]
fail s = []
我所读到的讨论似乎忽略了>>=
如何创建控制结构的问题,如do
符号所示:
allEvenOdds :: Int -> [(Int,Int)]
allEvenOdds n = do
evenValue <- [2,4 .. n]
oddValue <- [1,3 .. n]
return (evenValue,oddValue)
这是内置在Haskell中的吗,就像我假设的IO单子与实际i/o的接口一样?
2条答案
按热度按时间nszi6y051#
没有任何内置的东西,所有的一切都是你引用的Monad示例的简单结果(而且,由于这个例子使用
do
表示法,它是如何简化为>>=
运算符的用法的):您可以很容易地看到“迭代”两个列表,并得到一个包含所有(偶数,奇数)对的列表,其中的值取自两个列表。
在高层次上,我们可以说单子导致迭代,仅仅是因为
concatMap
像map
一样,对列表中的每个元素执行给定的函数,所以它隐式地迭代列表。vuktfyat2#
Monad
类型类模型的列表示例 * 非确定性 *:可以将每个var <- someList
看作是一个for
循环,就像Python中一样。do
表示法被去糖化为[2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue)))
,所以这相当于Python中的一些内容:或者使用列表解析:
这是因为对于
instance Monad []
,表达式[2,4 .. n] >>= (\evenValue -> [1, 3 .. n] >>= (\oddValue -> return (evenValue, oddValue)))
因此等效于:从而:
但是,
do
符号并没有“硬连接”到IO
:IO
只是Monad
的一个示例,它的实现方式是一个IO
操作在第二个之前运行。对于列表,它的实现方式等同于跨越Pythonfor
循环。