2013-06-06 11 views
6

Molti vincoli sembrano unirsi. Cerchiamo di astrarli.Fondi per famiglie di vincoli

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

MonadNumState è solo un sinonimo di vincolo, in modo da ottenere il beneficio di dipendenze funzionali ad ogni utilizzo, e può facilmente gettare una MonadNumState a m in un contesto. Ora, supponiamo che io desidero astratto questo in una famiglia vincolo:

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) 
    ... 

Ma ora a non è una dipendenza funzionale. next è praticamente inutilizzabile poiché a non può essere dedotto. Cosa posso fare? Beh, potrei, ovviamente, usare una famiglia tipo invece. MonadState viene scritto utilizzando fondi, ma dovrebbe essere facile convertire i fondi per digitare famiglie.

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

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

Indovina no.

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

Cos'altro potrei essere in grado di fare? Quello che voglio veramente è quantificare esistenzialmente s. Non ho trovato alcun modo per farlo senza passare del dizionario esplicito.

Quindi, come ottengo il beneficio di fondi per famiglie di vincoli?

risposta

3

È possibile considerare l'utilizzo di un tipo di famiglia autonomo invece di un tipo

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

Poi associati è possibile definire

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

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

e usarlo su una monade concreto come questo:

type instance StateType (State s) = s 
getState :: State s s 
getState = get' 
Problemi correlati