2017-05-17 16 views
1

同じ名前の2つの関数をHaskellで異なる数の引数にすることは可能ですか?これは私が何をしたいです:異なる数の引数を持つHas​​kell関数のオーバーロード

inc = (+) 1

inc x = (+) x

私が1ずつ増加への引数なしデフォルト値を持つ、または引数を指定して、私のインクリメント機能を呼び出し、それがインクリメント持つことができるようにしたいですxによって。

ザIは、例えば、次のいずれかを行うことができます[2,3,4]

map(inc 2)[1,2,3]

map(inc)[1,2,3] --results - [3,4,5]

における結果
+1

タイプクラスを介して複数の引数を持つ関数を持つことができます。ビットトリッキーは、たとえばDevelopment.Shake.cmdを参照してください。免責事項を追加したいのですが、これは初心者ではなく、もっと中間的なトピックです – epsilonhalbe

+6

もう1つの免責事項として、技術的に可能な状況であっても、ハスケルの開発者が実際にやっていることではありません。私たちは常に*使用しています。また、それは痛みです。 – luqui

+0

も参照してください:[増分アドホックパラメータ抽象化](https://byorgey.wordpress.com/2010/04/03/haskell-anti-pattern-incremental-ad-hoc-parameter-abstraction/)。 –

答えて

6

まず、簡単な選択肢は、このためだけにMaybeを取ることです「デフォルト引数」の種類:

inc :: Num a => Maybe a -> a -> a 
inc Nothing x = 1 + x 
inc (Just i) x = i + x 

そうでなければ、可能ですが、それはおそらく価値がありません。このテクニックは、具体的な型(操作の結果)と関数(より多くの引数を受け入れる)のインスタンスを持つ型クラスを作成することです。

私たちは、増分の結果としての役割を果たすことができます種類のクラスを紹介:

class Inc i where 
    inc :: Integer -> i 

、発信者が整数を要求した場合、我々は1ずつ増加:

instance Inc Integer where 
    inc = (+) 1 

、発信者の要求した場合整数を返す関数は、その関数の引数でインクリメントします。

instance (Integral a) => Inc (a -> Integer) where 
    inc x = (+) x . toInteger 

N OWこれらの作業の両方:

map inc [1, 2, 3] 
map (inc 2) [1, 2, 3] :: [Integer] 

しかし、結果は結果を使用して何かに[Integer]に拘束されない限り、型注釈が必要です。具体的なIntegerの代わりにNum a => aのようなジェネリック型を使用しようとした場合、またはのインスタンスに(Integral a) => Inc (a -> Integer)のインスタンスを置き換えて、のいずれかの引数を受け入れるようにすると、型推論はさらに悪化します。一方、IntDoubleのような他の具体的な型のインスタンスを追加することもできます。

私の疑問に答えると、あなたは実際にどのような問題を解決しようとしていますか?

1

いいえ、不可能です。 Haskellでは、関数の最新の定義が優先されます。ですから、INC。の両方のバージョンが定義されている場合:

inc = (+) 1 
inc x = (+) x 

を次に2番目の定義だろう最初の定義。つまり、 "inc"を呼び出すと、2番目の定義が使用されます。

しかし、あなたは部分的なアプリケーションでも、あなたが望むものを達成することができます。 2つのコールをカレンダーにすると、同じ効果が得られます。これと同じように:

map (inc 1) [1,2,3] 

戻り[2,3,4]

map (inc 2) [1,2,3] 

戻り[3,4,5]

関連する問題