如何定义一个由两个任意单子变换器组成的单子变换器?
How do define a monad transformer that is the composition of two arbitrary monad transformers?
我想写类似下面的东西:
newtype FooT c d m a = FooT { unFooT :: (c (d m)) a }
instance (MonadTrans c, MonadTrans d) => MonadTrans (FooT c d) where
lift = FooT . lift . lift
但是,此代码段无法编译:
Could not deduce (Monad (d m)) arising from a use of ‘lift’
我明白为什么这不会编译;我们不知道任意转换器 d m
的应用本身就是一个 monad。但是,我不确定继续进行的最佳方式。
有没有一种干净的方法可以使这样的工作起作用?如果我可以沿着 Monad (d m)
行向实例声明的左侧添加一个约束,大概它会通过,但我不知道该怎么做,因为 m
不是绑定。
使用 QuantifiedConstraints
GHC 扩展,这是
{-# LANGUAGE QuantifiedConstraints #-}
instance (MonadTrans c, MonadTrans d, forall m. Monad m => Monad (d m)) =>
MonadTrans (FooT c d) where
lift = FooT . lift . lift
约束中的 m
与 lift
中的 m
不同。量化约束只是意味着它所说的(“对于任何 m :: Type -> Type
,如果 Monad m
需要 Monad (d m)
”),并且在 lift
中,通用语句正在用特定的 m
作为参数传递给 lift
。因此 lift
的 m
没有超出其范围。
自 transformers 0.6 the MonadTrans
type class has had a requirement that it preserves Monad
.
这意味着MonadTrans
的定义是:
type Lifting cls trans = forall m. cls m => cls (trans m)
class Lifting Monad trans => MonadTrans trans where
lift :: Monad m => m ~> trans m
你称之为FooT
的变形金刚组合(ComposeT
)不需要指定提升,所以你在问题中提供的代码应该适用于版本0.6+.
ComposeT
already exists in deriving-trans
newtype Ok m a = Ok (Int -> Bool -> m a)
deriving
( Functor, Applicative, Alternative, Contravariant
, Monad, MonadPlus, MonadCont, MonadIO, MonadFix,
, MonadFail, MonadZip
)
via ReaderT Int (ReaderT Bool m)
deriving MonadTrans
via ComposeT (ReaderT Int) (ReaderT Bool)
我想写类似下面的东西:
newtype FooT c d m a = FooT { unFooT :: (c (d m)) a }
instance (MonadTrans c, MonadTrans d) => MonadTrans (FooT c d) where
lift = FooT . lift . lift
但是,此代码段无法编译:
Could not deduce (Monad (d m)) arising from a use of ‘lift’
我明白为什么这不会编译;我们不知道任意转换器 d m
的应用本身就是一个 monad。但是,我不确定继续进行的最佳方式。
有没有一种干净的方法可以使这样的工作起作用?如果我可以沿着 Monad (d m)
行向实例声明的左侧添加一个约束,大概它会通过,但我不知道该怎么做,因为 m
不是绑定。
使用 QuantifiedConstraints
GHC 扩展,这是
{-# LANGUAGE QuantifiedConstraints #-}
instance (MonadTrans c, MonadTrans d, forall m. Monad m => Monad (d m)) =>
MonadTrans (FooT c d) where
lift = FooT . lift . lift
约束中的 m
与 lift
中的 m
不同。量化约束只是意味着它所说的(“对于任何 m :: Type -> Type
,如果 Monad m
需要 Monad (d m)
”),并且在 lift
中,通用语句正在用特定的 m
作为参数传递给 lift
。因此 lift
的 m
没有超出其范围。
自 transformers 0.6 the MonadTrans
type class has had a requirement that it preserves Monad
.
这意味着MonadTrans
的定义是:
type Lifting cls trans = forall m. cls m => cls (trans m)
class Lifting Monad trans => MonadTrans trans where
lift :: Monad m => m ~> trans m
你称之为FooT
的变形金刚组合(ComposeT
)不需要指定提升,所以你在问题中提供的代码应该适用于版本0.6+.
ComposeT
already exists in deriving-trans
newtype Ok m a = Ok (Int -> Bool -> m a)
deriving
( Functor, Applicative, Alternative, Contravariant
, Monad, MonadPlus, MonadCont, MonadIO, MonadFix,
, MonadFail, MonadZip
)
via ReaderT Int (ReaderT Bool m)
deriving MonadTrans
via ComposeT (ReaderT Int) (ReaderT Bool)