2017-12-01 4 views
1

Haskell type familiesの記事に続いて、私はそれを自分で試して勇気を見つけました。ネイティブのHaskellリストには「本当の」型名がありますか?または...私はここで間違って何をしていますか?

{-# LANGUAGE TypeFamilies #-} 

class Iterable c where 
    data Iterator c :: * -> * 
    current :: Iterator c a -> Maybe a 
    next :: Iterator c a -> Maybe (Iterator c a) 

instance Iterable [] where 
    data Iterator [] a = ListIterator [a] -- Problem in this line! 
    current (ListIterator []) = Nothing 
    current (ListIterator (x:xs)) = Just x 
    next (ListIterator []) = Nothing 
    next (ListIterator (x:xs)) = Just (ListIterator xs) 

これは、上記のHaskellのチュートリアルで与えられたコード例のアナロジーである:まあリストは、私は右のアイデアを得た場合だけ見るために、すでにのApplicativeやその他もろもろであることを知って、私は次のことを実行しようとしました。 これは、ネイティブのHaskellリストのためにタイプファミリーIterableを一般的に実装することです。

私は data Iterator [a] = ListIterator [a]を書くために、代わりしようとしたが、これは私がここに表示されたコードと同じエラーメッセージが得られます。

temp.hs:8:19: error: 
    * Expecting one more argument to `[]' 
     Expected a type, but `[]' has kind `* -> *' 
    * In the first argument of `Iterable', namely `[]' 
     In the instance declaration for `Iterable []' 

そこで、私の質問、私の代わりにリストの実際の型の名前を使用するオプションを持っている場合[]の私の疑いのように、これは私の(構文的な)問題の原因です。

+1

ハスケルは本当に「*ネイティブ*」リストではないと思います。リストは、Haskellコンパイラによって実装されなければならないものではなく、データ構造 'data [a] = [] |として定義されています。 (a:[a]) 'となります。 –

+0

"temp.hs:13:37:error: データコンストラクタがスコープに含まれていません:いくつか:: a - >たぶん tempです。hs:15:34:error: データコンストラクタがスコープ内にありません: いくつか:: Iterator [] a - >多分(Iterator [] a) "ここに – BitTickler

+1

あなたが引用したエラーメッセージは' [] ' 'Iterable'の最初の引数として、' Iterator'や 'ListIterator'とは関係がありません。' * - > * '(真)の' [] 'と言います。なぜなら、GHCがそれを期待していた理由を説明していたのですが、エラーメッセージを注意深く読めば、これをデバッグするように正しい質問にもっと近づけることができました。 – Ben

答えて

4

クラスは実際には引数を全く使用しません。Iterator cのみを使用しますが、cを使用しないことに注意してください。それは基本的に大丈夫です– cは基本的にタグのように機能しますが、他のタイプの–を選択することはできますが、あなたが望むものであるかどうか、より直接的なアプローチが良くないかどうかを尋ねるべきです。

唯一の実際の問題:cはそれ自身では使用されないため、コンパイラは何がの種類であるかを知る方法がありません。つまり、基本的にあなたのクラスは多相でに分類されています。これはHaskell98では許可されていません...したがって、デフォルトは可能な最も単純な種類、つまり*です。 GHCiはこれをあなたに伝えます:

*Main> :k Iterable 
Iterable :: * -> Constraint 

instance Iterable IntInt*です。しかし、[]はありません、種類は* -> *です。したがって、そのエラーメッセージ。あなたはこのデフォルト化を避けるために、GHCのPolyKinds拡張を有効にすることができ

{-# LANGUAGE PolyKinds  #-} 

class Iterable c where 
    data Iterator c :: * -> * 
    current :: Iterator c a -> Maybe a 
    next :: Iterator c a -> Maybe (Iterator c a) 

は、今では(k ~ (* -> *)で)あまりにも

*Main> :k Iterable 
Iterable :: k -> Constraint 

ので、両方instance Iterable Intが動作します(k ~ *付き)とinstance Iterable []です。今

{-# LANGUAGE KindSignatures #-} 

class Iterable (c :: * -> *) where 
    data Iterator c :: * -> * 
    current :: Iterator c a -> Maybe a 
    next :: Iterator c a -> Maybe (Iterator c a) 

instance Iterable []は動作しますが、instance Iterable Intはないでしょう:

または、手動でcは常に親切* -> *を持つべきであると述べている可能性があります。

+0

"c is not used " - 私の意図は、' 'c''は' '* - > *' 'のような"コンテナ "型であり、' 'a''はコンテナの要素型です。 ? – BitTickler

+0

はい...しかし、あなたは、すべての_class interface_が知っているので、 'c'に何かを含むことはありません。あなたは単にt彼は 'Iterator'の引数です。したがって、コンパイラは、より複雑な種類の '* - > *'を 'c'に推論する理由を見ず、代わりに' * 'だけを選択します。 – leftaroundabout

+0

私は、この場合実際に何を意味するのかを表すような、種類の署名のアイデアが好きです。しかし...私の ''インスタンスIterable [] ''は、何らかの理由でコンパイルしていません。インスタンスのバージョンを教えてください。 – BitTickler

関連する問題