2017-02-08 34 views
0

我在学习Writer单子和有以下几点:Writer monad的函数组合?

myFunction :: Int -> Int -> Writer String Int 
myFunction e1 e2 
    | e1 > e2 = do 
     tell ("E1 greater") 
     return (e1) 
    | otherwise = do 
     tell ("E2 greater") 
     return (e2) 

main = do 
-- execWriter :: Writer w a -> w 
    print $ execWriter . myFunction 1 2 

错误:

"Couldn't match type ‘WriterT String Data.Functor.Identity.Identity Int’with ‘a0 -> Writer c0 a1’ 
    Expected type: a0 -> Writer c0 a1 
    Actual type: Writer String Int" 

为什么用.,而不是$这个计算错误?也许我对函数组合的理解是不正确的?

+0

好了' (。)::(b - > c) - >(a - > b) - > a - > c'运算符需要两个函数,每个函数带一个参数,右边的'myFunction'没有参数(或至少不是那个'execWriter'期待的。 –

+0

你也可以定义'(。:) =(。)。 (。)'然后使用'execWriter。:myFunction $ 1 2'。它也被称为“猫头鹰运营商”。 ('(。:)'已经在'Data.Composition'中定义 - http://hackage.haskell.org/package/composition-1.0.2.1/docs/Data-Composition.html) – zeronone

回答

4

函数组合与.意味着所得到的组合将收到一个参数。

此部分:

execWriter . myFunction 1 2 

可以更明确地这样写的:

(\x -> execWriter (myFunction 1 2 x)) 

由于myFunction只需要两个参数,你得到一个编译错误。

假如你在你的代码中使用$,像这样:

execWriter $ myFunction 1 2 

扩展生成的代码是相同的:

execWriter (myFunction 1 2) 

这是有效的。

2

除了乍得之说,发生这种情况的原因是常规功能应用程序(不使用$)的优先级高于所有运算符(中缀函数),包括.

,如果你有过这样写它你的例子会工作:

(execWriter . myFunction 1) 2 

即相当于:

(\x -> execWriter (myFunction 1 x)) 2 

,然后计算结果为:

execWriter (myFunction 1 2)