4

私はHaskellの初心者です。

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

data や 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

1 に答える 1

7

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

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

nは小文字でなければならないことに注意してください。これは、クラスを量子化する型変数であるためです。実際にインスタンスを定義したい場合は、次のようにインスタンス化 nNます。

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

整数に付属するすべての標準インスタンスはもちろん同じくらい良いです...

于 2016-07-30T16:27:55.827 に答える