似乎很多限制因素汇集在一起.让我们抽象出来.
type MonadNumState a m = (MonadState a m, Num a)
Run Code Online (Sandbox Code Playgroud)
MonadNumState
它只是一个约束同义词,所以我在每次使用时都能获得函数依赖的好处,并且可以轻松地将其MonadNumState a m
放入上下文中.现在,假设我希望将其抽象为约束族:
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)
...
Run Code Online (Sandbox Code Playgroud)
但现在a
不是功能依赖.next
实际上几乎无法使用,因为a
无法推断.我能做什么?当然,我可以使用类型系列代替.MonadState
是使用fundeps编写的,但应该很容易将fundeps转换为类型系列.
instance (MonadState s m) => MonadStateFamily m where
type St m = s
get' = get
...
instance (MonadStateFamily m) => MonadState (St m) m where
get = get'
...
Run Code Online (Sandbox Code Playgroud)
可能不会.
Foo.hs:25:3:
The RHS of an associated type declaration mentions type variable `s'
All such variables must be bound on the LHS
Run Code Online (Sandbox Code Playgroud)
我还能做些什么?我真正想要的是存在量化s
.没有明确的字典传递,我没有找到任何办法.
那么,我如何获得约束系列fundeps的好处呢?
小智 3
您可以考虑使用独立类型族而不是关联类型
type family StateType (m:: * -> *)
Run Code Online (Sandbox Code Playgroud)
然后你可以定义
class MonadStateFamily m where
get' :: m (StateType m)
instance (MonadState s m, s ~ StateType m) => MonadStateFamily m where
get' = get
Run Code Online (Sandbox Code Playgroud)
并在具体的 monad 上使用它,如下所示:
type instance StateType (State s) = s
getState :: State s s
getState = get'
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
264 次 |
最近记录: |