まず、同じ関数の異なる方程式に異なる型シグネチャを与えることはまったく不可能です。どの関数も、方程式の数に関係なく、1 つの型しか持てません。
第二に、負の制約は Haskell では適切な意味を持ちません (持たないでしょう)。クラス制約の意味を思い出してください。
f :: Num a => a -> a -> a
f x y = x + y
Num a
type ofは、型 classf
の任意のクラス メソッドをNum
type の値に適用できることを意味しますa
。一般的な動作を得るために、意識的に具象型に名前を付けていません。本質的に、私たちは「正確に何であるかは気にしませんが、操作がそれに適用できることa
は知っています」と言っています。Num
したがって、Num
メソッド onx
およびを使用できますy
が、それ以上は使用できません。つまり、メソッド onおよび以外は何も使用できません。これが型クラス制約とは何か、なぜ必要なのかです。関数の汎用インターフェイスを指定しています。Num
x
y
ここで、架空のnot Num a
制約を考えてみましょう。この声明はどのような情報をもたらしますか? a
それが であってはならないことはわかっていますNum
。しかし、この情報は私たちにとってまったく役に立ちません。検討:
f :: not Num a => a -> a
f = ???
の代わりに何を置けます???
か? 明らかに、私たちは配置できないものを知っています。ただし、この署名にはそれ以上の情報がないことを除いて
f :: a -> a
唯一の操作は次のf
とおりですid
(まあ、undefined
それも可能ですが、それは別の話です)。
最後にあなたの例を考えてみましょう:
showSquare :: (Show a, not Num a) => a -> String
showSquare x = "I don't know how to square " ++ (show x)
私はあなたの例の最初の部分を意図的に与えていません。私の答えの最初の文を見てください。異なるタイプの異なる方程式を持つことはできません。しかし、この機能だけではまったく役に立ちません。ここで制約を安全に削除できますがnot Num a
、何も変更されません。
Int
静的に型付けされた Haskell でのこのような負の制約の唯一の使用法は、たとえばfor not Num a
-constrainted 変数を指定したときにコンパイル時エラーを生成することです。しかし、これには何の役にも立ちません。