2016-07-30 15 views
1

私はハスケルの初心者です。haskellでクラスの型インスタンスを作成するには?

クラスの型のインスタンスを作成する方法があるかどうかを調べています。

データやnewtypeを使用せずにこのコードを使用する方法はありますか?

type N = ∀n. (n -> n) -> n -> n 

instance Printable N where 
     print :: N -> IO() 
     read :: String -> N 

私はGHCiの中にモジュールをロードしようとすると、それは私に語った:

Illegal polymorphic or qualified type: N 
In the instance declaration for ‘Printable N’ 
+4

は、なぜあなたは 'newtype'を使用したくない...単に同じように良いことは勿論である整数に来るすべての標準のインスタンスと

type N = Int 

やって、話しますか? – ErikR

+0

newtypeやデータを使っているなら 'newtype N = N(n - > n) - > n - > n' 'と書いて'(+)(N a)(N b) a + bをアンボックスすることなく '(+)= \ ab - > stuff'の代わりに' stuff = 'を使います。 – CheeseLollipop

+0

現行のGHCでは忍容性を避けることをお勧めします。 'newtype'や' data'を使うことはできません。 (また、 'newtype'を扱う方がずっと簡単になるような、安全な変換を探します)。 – chi

答えて

5

あなたがそこに書かれたものはクラス宣言、ないインスタンスのようにたくさん見えます。おそらく、あなたはこれを意味しましたか?

class Printable n where 
    print :: n -> IO() 
    read :: String -> n 

それはあなたがクラスを超える量子化するしている型変数だからnは、小文字にする必要があることに注意。あなたが実際にインスタンスを定義したい場合、あなたはよく、Nnをインスタンス化:

instance Printable N where 
    print n = ... 
    read str = ... 

をこの時点で型(クラス定義から)がすべて固定されている署名と何がする必要があります書き込みは、これらの関数の実際のバインディングなので、​​ではなく、=でなければなりません。

質問:あなたはどうして自分のクラスを必要としますか?すでにプレリュードに入っている標準機能printreadで名前の衝突が起こるだけです。 なし、定義することはできません:あなたが実際にやるべきことは、あなたが求めてきました実際の質問に取得するには、言った、あなたの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?それはかなり絶望的です。 正しいのことは、それを新しいタイプでラップすることです。普遍的な定量化を隠し、コンパイラが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の拡張機能がありますが、実際には機能しません。

ここでも、多型を公開しないことでこれらの問題を回避できます。Rank-Nタイプ(特にレンズ)にはいくつかの用途がありますが、ほとんどの場合、それらは完全に過剰で不必要です。そのような教会の数字を実際に使用する正当な理由は決してありません。

newtype N = Church { getChurch :: ∀ n . (n->n) -> n->n } 

任意のインスタンスまたは機能を問題なく定義できます。そして、実質的に

+0

申し訳ありませんが、私の質問をひどく説明しましたが、まだ正しく回答しました。ありがとうございます! – CheeseLollipop

関連する問題