作为练习,我试图手动实现前奏的有趣部分。每当我发现有机会自由点我就接受它。然而,这让我在最不可能的地方找到了一堵砖墙。使用此代码:
myelem _ [] = False
myelem x y = if x == head y then True else myelem x (tail y)
我正在尝试实施notElem
。以下是我的尝试:
-- First
mynotelem = not myelem
由于不匹配的类型,可以理解为什么会爆炸。这很容易解决:
-- Second
mynotelem x y = not (myelem x y)
然而,参数x和y的显式声明感觉很丑陋和不必要,所以我试着让它恢复到点自由风格。
-- Third
mynotelem = not $ myelem
哪个失败
Couldn't match expected type `Bool'
with actual type `a0 -> [a0] -> Bool'
In the second argument of `($)', namely `myelem'
In the expression: not $ myelem
In an equation for `mynotelem': mynotelem = not $ myelem
很公平,类型仍然不匹配。但你怎么解决它?你可以再次直接跳到
-- Fourth
mynotelem x y = not $ myelem x y
哪个有效,但似乎危险地接近于进入圈子。我发现可以消除其中一个论点:
-- Fifth
mynotelem x = not . (myelem x)
但那令人讨厌的x仍然存在。我该如何消除它?
答案 0 :(得分:12)
我们可以像这样重写你的代码:
mynotelem x = not . (myelem x)
= (not .) (myelem x)
现在认识到这只是h x = f (g x)
f = (not .)
和g = myelem
,因此我们可以使用(.)
运算符作为{{1}进行无点编写}}:
h = f . g
注意在使用具有更多参数的函数进行合成时,模式如何继续:
mynotelem = (not .) . myelem
或者,您也可以使用这种有趣的构图运算符组合来编写它:
> let f x y z = x+y+z
> (((sqrt .) .) . f) 1 2 3
2.449489742783178
对于更多参数,模式继续如下:
mynotelem = ((.).(.)) not myelem