あなたがそこに書いたものは、インスタンスではなく、クラス宣言によく似ています。おそらくあなたはこれを意味しましたか?
class Printable n where
print :: n -> IO ()
read :: String -> n
n
は小文字でなければならないことに注意してください。これは、クラスを量子化する型変数であるためです。実際にインスタンスを定義したい場合は、次のようにインスタンス化 n
しN
ます。
instance Printable N where
print n = ...
read str = ...
この時点で、型シグネチャはすべて (クラス定義から) 固定されており、記述する必要があるのはこれらの関数の実際のバインディング=
です::
。
質問: なぜ独自のクラスが必要なのですか? print
標準関数との名前の衝突を引き起こすだけで、read
それはすでにプレリュードにあります。実際にすべきことは、これらの標準クラスを自分のN
型でインスタンス化することです。つまり、
instance Show N where
show n = ...
instance Read N where
readsPrec _ str = ...
そうは言っても、あなたが尋ねた実際の質問にたどり着くには:いいえ、のような多相型のインスタンスを適切に定義することはできません∀ n . (n->n) -> n->n
。(Int->Int) -> Int->Int
コンパイラは、これを のようなより具体的なタイプ、または のようなより一般的なタイプとどのように区別することになってい∀ n m . (n->m) -> n->m
ますか? それはかなり絶望的です。正しいことは、単に newtype でラップすることです。これにより、全称量化が隠され、コンパイラーが他の型と適切に区別できるようになりN
ます。
または、直接受け入れ/生成するモノモーフィック関数を書くこともできますN
:
showChurch :: N -> String
showChurch n = ...
readsPrecChurch :: Int -> ReadS N
readsPrecChurch _ str = ...
ReadS N
実際、後者はすでに型システムには多すぎます。
readsPrecChurch :: Int -> String -> [(∀ n . (n->n) -> n->n, String)]
リスト内の普遍的な数量化? ええとああ。それは非予測的なタイプです。GHC には-XImpredicativeTypes
拡張機能がありますが、実際には機能しません。
繰り返しますが、ポリモーフィック型を公然と使用しないことで、これらの問題を回避してください。ランク N タイプ (特にレンズ) にはいくつかの優れた用途がありますが、ほとんどの場合、それらは完全にやり過ぎで不要です。そのような教会の数字を実際に使用する正当な理由は決してありません.
newtype N = Church { getChurch :: ∀ n . (n->n) -> n->n }
任意のインスタンスまたは関数を問題なく定義できます。そして、実際に言えば、単純に
type N = Int
整数に付属するすべての標準インスタンスはもちろん同じくらい良いです...