我正在阅读有关列表单子(monad)的在线Haskell书。在这本书中, list monad的定义如下:
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
fail _ = []
然后是一个 list monad用法的示例,如下所示:
Prelude> [1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
[(1,'a'),(1,'b'),(2,'a'),(2,'b')]
我是Haskell的新手,我的示例问题是,如何在
return (n,ch)
的lambda表达式中使用变量'n'。 n
在另一个lambda表达式中定义,我不理解为什么在一个lambda表达式中定义的变量在后续的lambda表达式中可用。我尝试根据列表monad定义转换如下示例:Prelude> concat (map (\ch -> return (n, ch)) (concat (map (\n -> ['a', 'b']) [1, 2])))
<interactive>:32:29: error: Variable not in scope: n
但是正如您所看到的,我收到一个错误消息,说变量
n
在其他lambda表达式的范围内不可用。也许这本书只是列出了列表monad定义的简化版本? 最佳答案
[1,2] >>= \n -> ['a','b'] >>= \ch -> return (n,ch)
不解析为
[1,2] >>= (\n -> ['a','b']) >>= (\ch -> return (n,ch))
但是作为
[1,2] >>= \n -> (['a','b'] >>= (\ch -> return (n,ch)))
您使用
concat / map
进行的翻译反射(reflect)了“错误”的解析。我们可以将其调整为正确的。第一个
>>=
变为concat (map (\n -> ???) [1,2])
现在我们可以根据需要翻译内部
>>=
并替换???
:??? = concat (map (\ch -> ???2) ['a','b'])
???2= return (n,ch)
结果:
concat (map (\n -> concat (map (\ch -> return (n,ch)) ['a','b'])) [1,2])
关于list - Haskell:列表monad中的变量范围,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/45377867/