2017-01-13 6 views
2

リストの2つの同じエントリを削除する関数を作成しようとしました。 (リストに2つの同一のエントリがあるとすぐに、それらを削除する必要があります)。再帰関数を実行すると、期待どおりに機能します。これは、パターンマッチングに依存しています:`f x = x`は` f = id`と等価ではありませんか?

f :: Eq a => [a] -> [a] 
f(a:b:xs)|a==b = f xs 
      |otherwise = a : f (b:xs) 
f x=x        -- if the list has less than two entries 

は、今私はしかし、我々はf=idように、第2のケースを書き換えることができますが、コード

f :: Eq a => [a] -> [a] 
f(a:b:xs)|a==b = f xs 
     |otherwise = a : f (b:xs) 
f = id 

のために私は理解していないエラー、以下の取得:

\path\to\my\program.hs:1:1: 
Equations for `f' have different numbers of arguments 
    \path\to\my\program.hs: 
(1,1)-(2,34) 
    \path\to\my\program.hs: 
3:1-6 
Failed, modules loaded: none. 

私は両方とも同じ数の引数を持っていますが、GHCは同意していないようです。

Try it online!

+0

'f = id'と言うと、文字通り' f'を 'id'のエイリアスにするだけです。このエラーは、関数定義の1つの形式から引数を省略することはできません。迷惑だが、大したことではない。 'x'を' id'に明示的に渡すだけです。もちろん、それは目的を破るので、あなたの最初の方法を使用してください。 – Carcigenicate

+0

ありがとう、それは面白いです。私はこのような例に遭遇したことはありません。私はしばらくの間、ハスケルで遊んでいました。これが言及されているチュートリアル/書籍/リファレンスをご存知ですか? – flawr

+0

いいえ、私はこれが誰もが最終的に実行するそれらの癖の一つだと思います。しかし、ほとんどの場合、ほとんどの場合、引数を省略した関数定義を書いているので、ポイントフリーの形式になっており、部分的に適用されている別の関数の短所に過ぎないので、 。 – Carcigenicate

答えて

5

関数の区分的定義はファーストクラスの構文ではないことに注意してください。それだけでsyntactic sugar for a case expression次のとおりです。

f :: Eq a => [a] -> [a] 
f = \x -> case x of 
      (a:b:xs) | a == b -> f xs 
        | otherwise -> a : f (b:xs) 
      x -> x 

これは、あなたが一枚に一枚から引数の数を変更できない理由を参照することが少し楽になります:コンパイラが正しくの最後の行に記入することはできませんcase式。

+3

さて、コンパイラは常に 'case'を生成する前にエタ拡張することができます。これは、以前の方程式が(seqと関数型のボトムが存在していても)すべての引数を持っていれば、セマンティクスを保つはずです。それでも、これは面白い見方です。 – chi

2

あなたは、機能の異なる方程式間のパラメータを不一致のエラーを取得します。だから、

valid (Just x) = ... 
valid _ = ... 

valid2 = ... 
valid2 = ... 

そして、これは失敗します。

invalid x = ... 
invalid = ... 

あなたが本当にidを使用したい場合、あなたはまだすることができ。それを使用する関数式のパラメータを省略し、ラムダのRHSに再導入します(私は個人的にそれを行うかどうかわかりませんが、状況によって異なります)。言われていること


は、GHCで、本当にf a = aからf = idの間に差があります。

GHCのインライナは、関数定義内にある同じ量のパラメータで呼び出される関数のみインライン化できます。

+0

ありがとう!ですから、 'g x = x'だけを考慮すると、' g = id'と完全に同じですか? – flawr

+1

@ flawr正解。 – MasterMastic

関連する問題