2016-04-15 6 views
0

データ型ファミリを使用してコンストラクタを隠す方法を理解しようとしています。与えられた簡単な例は、通常のペアなどから変換する操作を持つペアです。 bifunctorのインスタンスはコンパイルされません。エラーメッセージがタイプファミリー:ペアデータタイプファミリーのBifunctorをインスタンス化する方法は?

src/TypeFamilyTest.hs:66:21です: Bifunctorの最初の引数は一種* -> * -> *、 を持っていますが、Bifunctor (Pairs a b)、私は別の取得Bifunctor Pair where ...をしようと

ためのインスタンス宣言では一種ghc-prim-0.4.0.0:GHC.Prim.Constraint

Pairs a bている必要がありますエラーメッセージには同じGHC.Prim.Constraintが記載されています。インスタンスの正しい引数は何ですか?また、コンテキストはどのように渡されますか?

class Pairs a b where 
    data Vec2 a b 

    mkPair :: (a,b) -> Vec2 a b -- (FirstF a, SecondF a) -> a 
    splitPair :: Vec2 a b -> (a,b) 
    fstP :: Vec2 a b -> a 
    sndP :: Vec2 a b -> b 
    fstP = fst . splitPair 
    sndP = snd . splitPair 

instance () => Bifunctor (Pairs a b) where 
    bimap opv oph vh = mkPair (opv . fstP $ vh, oph . sndP $ vh) 
+3

データファミリはコンストラクタを隠すことではありません。それらのコンストラクタは、通常のデータ型と同じ方法で表示または非表示にすることができます。データ・ファミリは、非パラメトリック・データ型(型引数を検査してそのコンストラクタの外観を決定する型)に関するものです。 –

+1

タイプ・クラスはオブジェクト指向のクラスではありません。それはデータとその上で動作する操作をカプセル化しません。 – chepner

+0

ハスケル 'クラス 'に最も近いOOPの概念は、Javaのような'インタフェース 'であり、この対応関係も緩いです。 – chi

答えて

2

タイプエラーはあなたにすべてを伝えます。 Pairはデータ型の名前ではありません。それはクラスの名前です。 Pair a b :: ConstraintだからPair :: * -> * -> ConstraintBifunctorは、種類が* -> * -> *のデータ型でのみインスタンス化できます。

することは、私はあなたがこのような何かを意味している可能性が推測している:あなたはもともとVec2関連するタイプを作った理由

newtype Pair a b = Vec2 { splitPair :: (a, b) } 

fstP :: Pair a b -> a 
fstP = fst . splitPair 

sndP :: Pair a b -> b 
sndP = snd . splitPair 

instance Bifunctor Pair where 
    bimap f g (Vec2 (x, y)) = Vec2 (f x, g y) 

は、私は理解していません。私はこれがXY problemかもしれないと思う - あなたは本当に達成しようとしていますか?

+2

OPはオブジェクト指向プログラミングをシミュレートしようとしているようですが、 'Pairs'は' Vec2'をカプセル化する型です。彼らの試みが構文的に正しいことは偶然である。 – chepner

+0

便利な回答をいただきありがとうございます。私はクラスがあまりにも多く、関連するタイプの実験を開始したと感じるプログラムの混乱を減らそうとしていました。私は今、より良く理解しています。どのような関連タイプが有用であり、提案されたラインに沿ってソリューションを使用します。 - ありがとうございました! – user855443

関連する問題