应用箭头上的幺半群时出现意外结果

时间:2016-12-26 23:18:57

标签: haskell arrows

我有这个简单的“箭头”:

std::unique

std::set<>返回:

main = do
        let
        -- arr :: (Arrow a) => (b -> c) -> a b c
        -- (>>>) :: Category cat => cat a b -> cat b c -> cat a c
        -- (<+>) :: ArrowPlus a => a b c -> a b c -> a b c
        -- infixr 5 <+>
        -- infixr 1 >>>
        -- runKleisli :: Kleisli m a b -> a -> m b
          prepend x = arr (x ++)
          append  x = arr (++ x)

          xform = (prepend "<") >>> (append ">") <+> (prepend "{") >>> (append "}")
          xs = ["foobar"] >>= (runKleisli xform)
        mapM_ putStrLn xs

如果我将<+>替换为:

<foobar>}
{<foobar}

我明白了:

xform

为什么我得到这2个结果?即使查看xform = ((prepend "<") >>> (append ">")) <+> ((prepend "{") >>> (append "}")) s(作为代码中的注释)也无济于事。

2 个答案:

答案 0 :(得分:4)

让我们再说一点:

xform = prepend "<" >>> append ">" <+> prepend "<" >>> append ">"
xform' = (prepend "<" >>> append ">") <+> (prepend "<" >>> append ">")

现在xform,因为infixr 5 <+>infixl 1 >>>绑定得更紧,因此被解析为

xform = prepend "<" >>> (append ">" <+> prepend "<") >>> append ">"

如图所示

                           ┌─append ">"──┐
     ──────prepend "<"─────<             +>═══append ">"═════▶
                           └─prepend "<"─┘

xform'仅对应

            ┌─prepend "<"──append ">"─┐
     ───────<                         +>════▶
            └─prepend "<"──append ">"─┘

这应该解释一下。

答案 1 :(得分:4)

从您的问题中不清楚您期望它做什么。如果这个答案仍然没有帮助,写下您希望代码做的事情将有助于我们理解您的思考方式。

您正在使用的箭头是Kleisli [] - 即列表monad上的箭头。作为monad的列表是一个非确定性抽象 - 也就是说,列表表现得像可能性的集合。

Kliesli [] a b类型相当于a -> [b],被视为monadic函数,即:它需要一个输入并返回许多可能的输出。

<+>做的是通过每个参数转换输入,然后结合可能性。所以如果你运行箭头:

arr id <+> arr reverse

输入"hello",您将得到两个答案:

hello
olleh

如果你用任何东西组成,每种可能性都将被组成:

prepend "<" >>> (arr id <+> arr reverse)

然后你会得到

<hello
olleh<

因此正在考虑<+>的每个替代方案&#34;并行&#34;。 <出现在第二行的原因是因为输入arr reverse已经获得"<"前置。相比之下,如果你做了

(arr id <+> arr reverse) >>> prepend "<"

然后你得到

<hello
<olleh

这是有道理的,为什么你得到你现在做的输出?