2013-06-06 38 views
6

Wiele ograniczeń wydaje się zbierać. Rozdzielmy je.Fundeps dla rodzin z ograniczeniami

type MonadNumState a m = (MonadState a m, Num a) 

MonadNumState jest po prostu synonimem ograniczenia, więc uzyskać korzyści z zależnościami funkcjonalnymi w każdym użyciu i łatwo rzucać MonadNumState a m w kontekście. Teraz załóżmy, że chcę to streszczenie w rodzinie więzów:

class Iterator t where 
    type MonadIter t a m :: Constraint 
    next :: (MonadIter t a m) => m t 
    ... 

instance Iterator Foo where 
    type MonadIter Foo a m = (MonadState a m, Num a) 
    ... 

instance Iterator Bar where 
    type MonadIter Bar a m = (MonadRandom m, MonadSplit a m, RandomGen a) 
    ... 

Ale teraz a nie jest to zależność funkcjonalna. next praktycznie nie nadaje się do użytku od a nie można wywnioskować. Co mogę zrobić? Cóż, mógłbym oczywiście użyć rodziny typów. MonadState jest napisany przy użyciu programu fundss, ale powinno być łatwe przekształcanie znaków zachęty w typ rodziny.

instance (MonadState s m) => MonadStateFamily m where 
    type St m = s 
    get' = get 
    ... 

instance (MonadStateFamily m) => MonadState (St m) m where 
    get = get' 
    ... 

Zgadnij, nie.

Foo.hs:25:3: 
The RHS of an associated type declaration mentions type variable `s' 
    All such variables must be bound on the LHS 

Co jeszcze mogę zrobić? To, czego naprawdę chcę, to egzystencjalnie określić ilościowo: s. Nie znalazłem żadnego sposobu na to bez wyraźnego podania słownika.

Jak mogę uzyskać korzyści z fundeps dla rodzin z ograniczeniami?

Odpowiedz

3

Można rozważyć zastosowanie autonomicznego rodzinę typu zamiast powiązanego typu

type family StateType (m:: * -> *) 

Następnie można zdefiniować

class MonadStateFamily m where 
    get' :: m (StateType m) 

instance (MonadState s m, s ~ StateType m) => MonadStateFamily m where 
    get' = get 

i używać go na betonowym monady jak ten:

type instance StateType (State s) = s 
getState :: State s s 
getState = get' 
Powiązane problemy