2

演習として、プレリュードの興味深い部分を手動で実装しようとしています。ポイントフリーになる機会を見つけたときはいつでもそれを取ります。しかし、これは私を最もありそうもない場所のレンガの壁に導きました。このコードの使用:

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

これは機能しますが、危険なほど円を描くことに近いようです。私は、議論の1つを排除することが可能であることを発見しました:

-- Fifth
mynotelem x = not . (myelem x)

しかし、その厄介なxはまだ残っています。どうすればそれを排除できますか?

4

1 に答える 1

12

次のようにコードを書き直すことができます。

mynotelem x = not . (myelem x)
            = (not .) (myelem x)

これはとだけh x = f (g x)であることに注意してください。次のように演算子を別の方法で使用して、ポイントフリーで記述できます。f = (not .)g = myelem(.)h = f . g

mynotelem = (not .) . myelem

より多くの引数を持つ関数で作成するときに、パターンがどのように続くかに注意してください。

> let f x y z = x+y+z
> (((sqrt .) .) . f) 1 2 3
2.449489742783178

あるいは、この変な見た目の合成演算子の合成でそれを書くこともできます:

mynotelem = ((.).(.)) not myelem

その他の引数については、パターンは次のように続きます。

> ((.).(.).(.)) sqrt f 1 2 3
2.449489742783178
于 2011-12-28T02:31:12.870 に答える