Haskell:为什么f1。 f2 xy不工作?

时间:2014-11-05 00:54:10

标签: haskell function-composition dot-operator

我对点运算符有点困惑。我有以下代码(用于测试):

test :: Int -> Int -> Int
test x y = f1 . f2 x y 
           where f1 n = n+1
                 f2 x' y' = x' * y'

我认为它会首先执行(f2 x y)然后执行该结果的f1,但它会抛出错误。谁能告诉我点运算符的确切定义以及等于 f1的内容。 f2 x y ? (在没有点运算符的情况下编写)

祝你好运, Skyfe。

编辑:如果点运算符产生一个完整的新函数,我认为以下代码应该起作用:

test :: Int -> Int -> Int
test x y = f1 . f2 x
           where f1 n = n+1
                 f2 x' y' = x' + y'

但该代码也会返回错误。

3 个答案:

答案 0 :(得分:7)

在Haskell中,中缀运算符的优先级低于函数应用程序,所以

f1 . f2 x

像这样解析

f1 . (f2 x)

但是,f2 x不属于类型函数(好吧,如果f2返回一个函数,可能就是这样,但一般来说,或者问题不是这样)。由于(。)作用于函数,因此无法工作。

使用($)代替

f1 $ f2 x

答案 1 :(得分:2)

一种常见方法是将(.)($)合并:

f1 . f2 $ x

这可以很容易地扩展,以建立更长的“管道”:

f1 . f2 . f3 . f4 $ x

然后,如果您发现自己在其他地方需要相同的组合,则只需要剪切和粘贴:

fs = f1 . f2 . f3 . f4

... fs x ... fs y

答案 2 :(得分:2)

(我认为其他答案太快了$

如您所知,

f1 . f2 x

被解析为

f1 . (f2 x)

(f1 . f2) x

而是执行以下操作:撰写f2f1,然后将此组合函数应用于x。现在

($) :: (a -> b) -> a -> b
f $ x = f x

看起来多余了。它的主要目的是它具有最低优先级,因此您可以避免使用括号:

foo . bar . baz $ x + y * z = (foo . bar . baz) (x + y * z)

另请参阅:Haskell: difference between . (dot) and $ (dollar sign)