Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
通过列表单子理解haskell列表理解_Haskell - Fatal编程技术网

通过列表单子理解haskell列表理解

通过列表单子理解haskell列表理解,haskell,Haskell,我来自python世界,但尽量使用functional,并改变我的命令式思维 现在我研究haskell发现 list = [(x,y) | x<-[1,2,3], y<-[4,5,6]] 我试图逐步了解列表单子绑定链的处理: 绑定定义为: xs >>= f = concat (map f xs) 而bind是左关联的 正如我所理解的,在开始时,第一个绑定([1,2,3]>=\x->[4,5,6])被执行,结果是[4,5,6,4,5,6,4,5,6] 然后下一个绑定 [

我来自python世界,但尽量使用functional,并改变我的命令式思维

现在我研究haskell发现

list = [(x,y) | x<-[1,2,3], y<-[4,5,6]]
我试图逐步了解列表单子绑定链的处理:

绑定定义为:

xs >>= f = concat (map f xs)
而bind是左关联的

正如我所理解的,在开始时,第一个绑定([1,2,3]>=\x->[4,5,6])被执行,结果是[4,5,6,4,5,6,4,5,6]

然后下一个绑定 [4,5,6,4,5,6,4,5,6]>>=\y->执行返回(x,y)

但是如果它是allready计算的,它怎么能看到lambda中的x呢??x只是一个根本没有具体值的参数(lambda可以在任何时候用varios参数调用,我们如何在外部使用它并修复??)。如果它能看到它怎么知道x呼叫历史记录被1,2,3改变了?根据我的理解,一旦第一次绑定计算完成,只有结果[4,5,6,4,5,6,4,5,6]是可用的,然后是下一个绑定的第一个参数


因此,我不明白我如何阅读这个结构,以及它如何一步一步地逻辑地产生正确的结果?

这是一个常见的混淆源。lambdas的范围尽可能扩展,因此:

[1,2,3] >>= \x ->
[4,5,6] >>= \y ->
return (x,y)
相当于:

[1,2,3] >>= (\x ->
  [4,5,6] >>= (\y ->
    return (x,y)))
因此内部lambda
\y->…
在外部lambda的范围内,
\x->…
,意味着
x
y
都在范围内。然后,您可以为
[]
monad实例内联
>=
返回
的定义,并逐步完成求值:

concatMap (\x ->
  concatMap (\y ->
    [(x,y)]) [4,5,6]) [1,2,3]

concat
  [ concatMap (\y -> [(1,y)]) [4,5,6]
  , concatMap (\y -> [(2,y)]) [4,5,6]
  , concatMap (\y -> [(3,y)]) [4,5,6]
  ]

concat
  [ concat [[(1,4)], [(1,5)], [(1,6)]]
  , concat [[(2,4)], [(2,5)], [(2,6)]]
  , concat [[(3,4)], [(3,5)], [(3,6)]]
  ]

concat
  [ [(1,4), (1,5), (1,6)]
  , [(2,4), (2,5), (2,6)]
  , [(3,4), (3,5), (3,6)]
  ]

[ (1,4), (1,5), (1,6)
, (2,4), (2,5), (2,6)
, (3,4), (3,5), (3,6)
]
fmap
)和
ap
)操作符或
liftA2
,用
应用程序的
实例而不是
Monad
实例来表达这一点,这是一种常见且更简洁的方式:

(,) <$> [1,2,3] <*> [4,5,6]

liftA2 (,) [1,2,3] [4,5,6]
(,)[1,2,3][4,5,6]
liftA2(,)[1,2,3][4,5,6]
(,) <$> [1,2,3] <*> [4,5,6]

liftA2 (,) [1,2,3] [4,5,6]