我已经开始围绕它,而更喜欢将它用于简单的情况,在这种情况下我可以将值从一个输出管道输出到一个输入。一个我喜欢的无点组合的简单例子是:
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
感到困惑?任何人都可以帮我理解这种构图背后的逻辑吗?
答案 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)
显式使用 curry
和 uncurry
有助于在“多参数”和单参数函数之间切换。
ne = curry (not . uncurry (==))
uncurry
“修正” (==)
使其采用单个参数 (x,y)
而不是单独的 x
和 y
参数。然后可以按预期使用 not
组合生成的函数。组合函数,然后可以重新柯里化以再次接受单独的参数。