2010-04-07 12 views
9

Ten kod kompiluje grzywny:Problem podczas mieszania klasy typu i rodzin typu

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, 
    UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables, 
    TypeOperators, TypeSynonymInstances, TypeFamilies #-} 
class Sel a s b where 
    type Res a s b :: * 

instance Sel a s b where 
    type Res a s b = (s -> (b,s)) 

instance Sel a s (b->(c,a)) where 
    type Res a s (b->(c,a)) = (b -> s -> (c,s)) 

ale jak tylko dodać GHC R źródłowe nie:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, 
    UndecidableInstances, FlexibleContexts, EmptyDataDecls, ScopedTypeVariables, 
    TypeOperators, TypeSynonymInstances, TypeFamilies #-} 
class Sel a s b where 
    type Res a s b :: * 

instance Sel a s b where 
    type Res a s b = (s -> (b,s)) 

class R a where 
    type Rec a :: * 
    cons :: a -> Rec a 
    elim :: Rec a -> a 
instance Sel a s (b->(c,Rec a)) where 
    type Res a s (b->(c,Rec a)) = (b -> s -> (c,s)) 

twierdząc, że:

Illegal type synonym family application in instance: 
     b -> (c, Rec a) 
    In the instance declaration for `Sel a s (b -> (c, Rec a))' 

co to znaczy i (co najważniejsze) jak to naprawić?

Dzięki

+2

Żaden pierwszy fragment kodu nie kompiluje się dobrze dla mnie. GHC (6.12.1) narzeka na "Sprzeczne deklaracje instancji rodzinnych". – kennytm

Odpowiedz

12

typu rodziny są jednokierunkowy: można rozszerzyć Rec a do tego typu komputerowej, ale nie można (jednoznacznie) jechać z powrotem do Rec a ekspansji. Powoduje to, że aplikacje funkcji typów są nieodpowiednie dla sygnatur instancji, ponieważ nie mogą wywołać instancji do zastosowania.

Można spróbować zamiast:

instance Rec a ~ reca => Sel a s (b->(c,reca)) 

Oznacza to coś innego: mówi dowolnej funkcji b -> (c, reca) jest instancją, a kiedy to nieodwołalnie dopasowane sprawdza kompilator Rec a ~ reca. Ale może to być wystarczająco dobre, by zrobić w twoim przypadku.

1

Rec nie jest konstruktorem typu; jest to funkcja typu. Może możesz używać go tylko w typie wartości definicji typu, a nie w deklaracji klasy? Zgaduję dziko tutaj; Nie rozumiem wszystkich zasad dla rodzin typów.

nie wiem jak to naprawić, ale pewne rzeczy, aby spróbować to:

  • Pozbądź klasy Sel i wystarczy zdefiniować type family Res a s b :: *. Użyj mechanizmu type instance zamiast mechanizmu klasy.

  • To prawie niemożliwe, że wprowadzenie typu Rec z użyciem iniekcji data pomoże, ale nie sądzę.

  • Ogranicza się do najmniejszej liczby rozszerzeń językowych, które mogą pracować — ułatwi innym pomoc, a także może pomóc kompilatorowi.

+1

Przełączanie na "dane" zadziała - rodziny danych są dozwolone w głowicach instancji, natomiast rodziny synonimów typów nie. –

1

Oznacza to, że nie można używać rodzin synomii typu podczas deklarowania instancji typu. Zobacz rozdział "Type families and instance declarations" w podręczniku GHC.

Jedynym sposobem na naprawienie tego jest refaktor, aby go jakoś nie potrzebować.

Powiązane problemy