这怎么阻止工作?

时间:2014-10-30 17:31:52

标签: haskell syntax

几周前我刚刚开始学习haskell,我看到了这个:

moves = do
    f <- [(+), subtract]
    g <- [(+), subtract]
    (x, y) <- [(1, 2), (2, 1)]
    [f x *** g y]

我之前没有看到do块以list结尾,它是骑士巡回问题解决方案的一部分。有人可以解释它是如何工作的吗?

1 个答案:

答案 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]

所以你看到它在两个元素列表上的嵌套折叠。 展开褶皱留给读者练习:)