haskell列表理解通过列表monad理解
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了haskell列表理解通过列表monad理解相关的知识,希望对你有一定的参考价值。
我来自python世界,但尝试尽可能多地使用功能,并改变我的命令性思维。
现在我研究haskell并发现了
list = [(x,y) | x<-[1,2,3], y<-[4,5,6]]
被翻译成
list' =
[1,2,3] >>= x ->
[4,5,6] >>= y ->
return (x,y)
我试着逐步理解list monad绑定链的处理:
绑定定义为:
xs >>= f = concat (map f xs)
并且绑定是左关联的
据我所知,在开始时首先绑定([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 - > return(x,y)执行
但是如果它已经计算好了怎么能看到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实例内联return
和[]
的定义,并逐步完成评估:
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)
]
一个常见且更简洁的表达方式是使用Applicative
实例而不是Monad
实例,使用<$>
(fmap
)和<*>
(ap
)运算符或liftA2
:
(,) <$> [1,2,3] <*> [4,5,6]
liftA2 (,) [1,2,3] [4,5,6]
以上是关于haskell列表理解通过列表monad理解的主要内容,如果未能解决你的问题,请参考以下文章