2014-12-15 4 views
14

Hier ist mein Code:Typ Familien Shenanigans in GHCi

{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds, PolyKinds, FlexibleContexts, UndecidableInstances #-} 

module Foo where 

import Data.Singletons.Prelude 
import Data.Type.Equality 

data TP a b 

-- foldl (\(bool, r) x -> (bool && (r == x), r)) (True, head xs) xs 
type family Same (b :: Bool) (r :: k) (rq :: [k]) :: k where 
    Same bool r (x ': xs) = Same (bool :&& (r == x)) r xs 
    Same bool r '[] = TP bool r 

data NotEqualFailure 
-- converts a True result to a type 
type family EqResult tp where 
    EqResult (TP 'True r) = r 
    EqResult (TP 'False r) = NotEqualFailure 



data Zq q i 
type family Foo rq 
type instance Foo (Zq q i) = i 
type R = 
    EqResult 
    (Same 'True (Foo (Zq Double Int)) 
     (Map (TyCon1 Foo) 
     '[Zq Double Int, Zq Float Int])) 

f :: R 
f = 3 

Dies kompiliert nicht in GHC 7.8.3:

No instance for (Num NotEqualFailure) 
     arising from a use of ‘f’ 
    In the expression: f 
    In an equation for ‘it’: it = f 

aber wenn ich f Kommentar und starten GHCi:

> :kind! R 
R :: * 
= Int 

So GHC kann nicht scheinen zu entscheiden, ob die Elemente in meiner Liste gleich sind oder nicht. Wenn sie gleich sind, sollte EqResult den allgemeinen Typ (Int hier) zurückgeben, andernfalls gibt NotEqualFailure zurück. Kann mir jemand erklären, was hier vor sich geht? Lassen Sie es mich wissen, wenn Sie auch denken, dass dies wie ein Fehler aussieht, und ich werde es auf dem GHC-Trac ablegen.

Wenn Sie eine Möglichkeit finden, "EqResult (Same ...)" auf eine andere Weise zu schreiben, kann es dieses Problem umgehen.


EDIT schrieb ich die Art Familie, aber leider im Wesentlichen das gleiche Problem, das ich habe. Der Code ist jetzt kleiner und einfacher.

{-# LANGUAGE TypeFamilies, TypeOperators, DataKinds, FlexibleContexts, UndecidableInstances #-} 

module Foo where 

import Data.Singletons.Prelude 
import Data.Singletons.Prelude.List 
import Data.Type.Equality 

-- foldl (\(bool, r) x -> (bool && (r == x), r)) (True, head xs) xs 
type family Same rq where 
    Same (x ': xs) = 
    EqResult (And (Map ((TyCon2 (==)) $ x) xs)) x 

data NotEqualFailure 
-- converts a True result to a type 
type family EqResult b v where 
    EqResult 'True r = r 
    EqResult 'False r = NotEqualFailure 

type R = Same '[Int, Int] 

f :: R 
f = 3 

GHCi noch R-Int lösen, aber GHC kann die Schriftfamilie für EqResult überhaupt jetzt nicht lösen (bevor es falsch, es zu NotEqualFailure aufgelöst). Beachten Sie, dass dieses Beispiel funktioniert, wenn ich die Größe der Liste in eins ändere, d. H. '[Int].


EDIT 2 entfernte ich alle externen Bibliotheken und bekam alles zu arbeiten. Diese Lösung ist wahrscheinlich die kleinste, aber ich möchte immer noch wissen, warum die größeren Beispiele GHC zu brechen scheinen.

{-# LANGUAGE TypeFamilies, DataKinds, 
      UndecidableInstances #-} 

module Foo where 

type family Same (rq :: [*]) :: * where 
    Same (x ': xs) = EqTo x xs 

--tests if x==y for all x\in xs 
type family EqTo y xs where 
    EqTo y '[] = y 
    EqTo y (y ': xs) = EqTo y xs 
    EqTo y (x ': xs) = NotEqualFailure 

data NotEqualFailure 

type R = Same '[Int, Int] 
f :: R 
f = 3 
+0

Ich habe auch eine Vielzahl von Lösungen ausprobiert, und es scheint, dass Dinge brechen, wenn wir 'Map' in das Bild bringen. Ich habe es auch mit einer einfacheren Map versucht (nicht defunktionalisiert wie die Single-Version), aber es hat auch nicht funktioniert. –

+0

Woo hoo, jetzt ist es ein [ghc ticket] (https://ghc.haskell.org/trac/ghc/ticket/9888). – crockeea

Antwort