具有多个变量的无点组合

时间:2012-09-13 15:18:21

标签: haskell function-composition pointfree

我已经开始围绕它,而更喜欢将它用于简单的情况,在这种情况下我可以将值从一个输出管道输出到一个输入。一个我喜欢的无点组合的简单例子是:

let joinLines = foldr (++) "" . intersperse "\n"

今天在玩GHCI时,我想看看我是否可以撰写not(==)来复制(/=),但我真的无法推理出来。 (==)需要两个输入,而not需要一个输入。我认为这可能有用:

let ne = not . (==)

假设Bool的单个(==)输出将转到not,但它不会编译,引用以下错误:

<interactive>:1:16:
    Couldn't match expected type `Bool' with actual type `a0 -> Bool'
    Expected type: a0 -> Bool
      Actual type: a0 -> a0 -> Bool
    In the second argument of `(.)', namely `(==)'
    In the expression: not . (==)

我希望我能说这对我来说意义重大,但我所得到的只是传递给(==)的第二个论点可能会让not感到困惑?任何人都可以帮我理解这种构图背后的逻辑吗?

3 个答案:

答案 0 :(得分:14)

如果你当时开始删除一个参数,你会得到

ne x y = not (x == y)
       = (not . (x ==)) y
ne x   = not . (x ==)
       = not . ((==) x)
       = ((not .) . (==)) x
ne     = (not .) . (==)

基本上,对于每个参数,您需要一个(.),正确关联。

(==)的类型为Eq a => a -> a -> Bool。因此,如果您编写whatever . (==),并将值x传递给该whatever ((==) x),则会得到(==) x,但a -> Bool是一个函数a(其中x }是Eq的类型,以及whatever的实例。所以{{1}}必须接受函数类型的参数。

答案 1 :(得分:12)

另一个有用的运算符是(。:),它是一个带有两个参数的初始函数的组合子:

f . g  $ x
f .: g $ x y

答案 2 :(得分:3)

显式使用 curryuncurry 有助于在“多参数”和单参数函数之间切换。

ne = curry (not . uncurry (==))

uncurry “修正” (==) 使其采用单个参数 (x,y) 而不是单独的 xy 参数。然后可以按预期使用 not 组合生成的函数。组合函数,然后可以重新柯里化以再次接受单独的参数。