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?