6

许多限制似乎汇集在一起​​​​。让我们把这些抽象出来。

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

MonadNumState只是一个约束同义词,所以我在每次使用时都能从函数依赖中受益,并且可以轻松地将 aMonadNumState 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)
  ...

但现在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'
  ...

可能不会。

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

我还能做什么?我真正想要的是存在量化s。如果没有明确的字典传递,我还没有找到任何方法来做到这一点。

那么,我如何为受限制的家庭获得fundeps的好处?

4

1 回答 1

3

您可以考虑使用独立类型族而不是关联类型

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

然后你可以定义

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

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

并在这样的具体单子上使用它:

type instance StateType (State s) = s
getState :: State s s
getState = get' 
于 2013-06-07T07:19:51.940 回答