2013-06-06 24 views
6

Bir çok kısıtlama bir araya geliyor gibi görünüyor. Bunları soyutlayalım.Kısıtlama aileleri için Fundeps

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

MonadNumState sadece bir kısıtlama eşanlamlı olduğunu, bu yüzden her kullanımda fonksiyonel bağımlılıkları faydayı ve kolayca bir bağlam içine MonadNumState a m atabilir.

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

Ama şimdi a işlevsel bağımlılık değil: Şimdi, bir kısıtlama ailenin bu soyut isteyen varsayalım. next, a çıktısı alınamadığından hemen hemen kullanılamaz. Ne yapabilirim? Tabii ki, bunun yerine bir tip aile kullanabilirim. MonadState, fundeps kullanılarak yazılmıştır, ancak fundep'leri yazım ailelerine dönüştürmek kolay olmalıdır.

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

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

Tahmin edin.

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

Başka neler yapabilirim? Gerçekten istediğim, s'u varoluşsal olarak ölçmektir. Açık bir sözlük geçmeden bunu yapmanın hiçbir yolunu bulamadım.

Kısıtlama aileleri için nasıl eğlencelerden yararlanabilirim?

Eğer

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

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

tanımlamak ve bunun gibi bir somut monad üzerinde kullanabilirsiniz Sen ilişkili bir tip Sonra

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

yerine tek başına bir tip ailesini kullanarak düşünebiliriz

cevap

3

:

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