2016-12-26 40 views
3

我有这个简单的 “箭”:意外的结果当上箭头一个Monoid的应用

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有:

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

我收到:

<foobar> 
{foobar} 

为什么我会得到这2个结果?即使在infixr s(作为代码中的注释)也没有什么帮助。

+0

[这可能会让你的解决方案](http://stackoverflow.com/questions/40331179/how-to-automatically-parenthesize-arbitrary-haskell-expressions)。 – Alec

回答

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 ">"─┘ 

这应该解释它。

+0

谢谢!非常清楚(和你的图表是惊人的;)) – Randomize

4

从你的问题中不清楚你期待它做什么。如果这个答案仍然没有帮助,那么写下你期望的代码将会帮助我们理解你的想法。

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

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

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

arr id <+> arr reverse 

与输入"hello",那么你会得到两个答案:

hello 
olleh 

如果您有什么组成的,每种可能性将组成:

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

,那么你会得到

<hello 
olleh< 

因此<+>的每个替代方案都被视为“并行”。<来到第二行的原因是因为输入arr reverse正在获得已经有"<"前置。相反,如果你做了

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

然后你得到

<hello 
<olleh 

这是决策意识为什么你现在做的输出?

+0

谢谢你的回答,这是非常明确的。 @leftaroundabout的图表也阐明了很多。 – Randomize