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ğerclass 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