几周前我刚刚开始学习haskell,我看到了这个:
moves = do
f <- [(+), subtract]
g <- [(+), subtract]
(x, y) <- [(1, 2), (2, 1)]
[f x *** g y]
我之前没有看到do
块以list
结尾,它是骑士巡回问题解决方案的一部分。有人可以解释它是如何工作的吗?
答案 0 :(得分:6)
你必须贬低这种符号。首先写下类型:
import Control.Arrow
moves :: [(Integer, Integer) -> (Integer, Integer)]
moves = do
f <- [(+), subtract]
g <- [(+), subtract]
(x, y) <- [(1, 2), (2, 1)]
[f x *** g y]
所以我们在[]
(列表)monad。
查找Monad []的定义:
instance Monad [] where
m >>= k = foldr ((++) . k) [] m
m >> k = foldr ((++) . (\ _ -> k)) [] m
return x = [x]
将do notation翻译为bind并返回:
moves =
[(+), subtract] >>= \f ->
[(+), subtract] >>= \g ->
[(1, 2), (2, 1)] >>= \(x,y) ->
[f x *** g y]
然后,最后,根据他们的定义重写绑定:
按名单上的return
moves =
[(+), subtract] >>= \f ->
[(+), subtract] >>= \g ->
[(1, 2), (2, 1)] >>= \(x,y) ->
return (f x *** g y)
&gt;&gt; =
的定义moves =
foldr ((++) . (\f ->
[(+), subtract] >>= \g ->
[(1, 2), (2, 1)] >>= \(x,y) ->
return (f x *** g y)
)) [] [(+), subtract]
&gt;&gt; =
的定义moves =
foldr ((++) . (\f ->
foldr ((++) . (\g ->
[(1, 2), (2, 1)] >>= \(x,y) ->
return (f x *** g y))
) [] [(+), subtract]
)) [] [(+), subtract]
&gt;&gt; =
的定义moves =
foldr ((++) . (\f ->
foldr ((++) . (\g ->
foldr ((++) . (\(x,y) -> return (f x *** g y))
) [] [(1, 2), (2, 1)]
)) [] [(+), subtract]
)) [] [(+), subtract]
撤消退货:
moves =
foldr ((++) . (\f ->
foldr ((++) . (\g ->
foldr ((++) . (\(x,y) -> [f x *** g y])
) [] [(1, 2), (2, 1)]
)) [] [(+), subtract]
)) [] [(+), subtract]
所以你看到它在两个元素列表上的嵌套折叠。 展开褶皱留给读者练习:)