2016-04-15 12 views
0

Ich versuche zu verstehen, wie Datentypfamilien verwendet werden können, um einen Konstruktor zu verstecken. Das triviale Beispiel ist ein Paar mit Operationen zum Konvertieren von und zu gewöhnlichen Paaren usw.). Eine Instanz für bifunctor wird nicht kompiliert. die FehlermeldungTyp Familien: wie Bifunctor für eine Paardatentypfamilie instanziieren?

src/TypeFamilyTest.hs:66:21: Das erste Argument von Bifunctor sollte Art * -> * -> * haben, aber Pairs a b hat Art ghc-prim-0.4.0.0:GHC.Prim.Constraint

In der Instanzdeklaration für Bifunctor (Pairs a b)

Bifunctor Pair where ... Der Versuch, ich eine andere Fehlermeldung, die das gleiche auflistet GHC.Prim.Constraint. Was sind die richtigen Argumente für die Instanz und wie wird der Kontext übergeben?

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

In Datenfamilien geht es nicht darum, Konstruktoren zu verbergen. Ihre Konstruktoren können auf die gleiche Weise wie normale Datentypen ein- oder ausgeblendet werden. Datenfamilien sind nicht-parametrische Datentypen - Typen, die ihre Typargumente überprüfen, bevor sie entscheiden, wie ihre Konstruktoren aussehen. –

+1

Eine Typklasse ist keine Klasse im objektorientierten Sinne. Es kapselt Daten und die Operation, die daran arbeiten, nicht ein. – chepner

+0

Der nächste OOP-Begriff einer Haskell-'Klasse' ist eine Java-ähnliche' Schnittstelle', und selbst diese Korrespondenz ist lose. – chi

Antwort

2

Der Fehlertyp sagt Ihnen alles. Pair ist nicht der Name eines Datentyps. Es ist der Name einer Klasse. Pair a b :: Constraint so Pair :: * -> * -> Constraint. Bifunctor kann nur durch Datentypen der Art * -> * -> * instanziiert werden.

Ich vermute, Sie so etwas wie dies gemeint haben:

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) 

Ich verstehe nicht, warum Sie ursprünglich Vec2 ein zugehöriges Art gemacht. Ich vermute, das könnte ein XY problem sein - was willst du wirklich erreichen?

+2

Es sieht so aus, als ob das OP versucht, objektorientierte Programmierung zu simulieren, wobei "Paare" ein Typ ist, der ein 'Vec2' einkapselt. Es ist ein Zufall, dass ihr Versuch syntaktisch korrekt ist. – chepner

+0

Ich schätze die hilfreichen Antworten. Ich habe versucht, Unordnung in einem Programm zu reduzieren, in dem ich fühle, dass ich zu viele Klassen habe und mit dem zugehörigen Typ experimentiere. Ich verstehe jetzt besser, welche verbundenen Typen nützlich sind und eine Lösung entlang der vorgeschlagenen Linien verwenden werden. - Danke! – user855443