STT的管道吊装方法
How to hoist Conduit of STT
我一直在尝试编写函数的实现:
foo :: Monad m => ConduitM i o (forall s. STT s m) r -> ConduitM i o m r
但我每次都因错误而失败:
Couldn't match type because variable `s` would escape its scope.
我现在怀疑实现这个功能是不可能的。
threadSTT :: Monad m
=> (forall a. (forall s. STT s m a) -> m a)
-> ConduitM i o (forall s. STT s m) r
-> ConduitM i o m r
threadSTT runM (ConduitM c0) =
ConduitM $ \rest ->
let go (Done r) = rest r
go (PipeM mp) = PipeM $ do
r <- runM mp -- ERROR
return $ go r
go (Leftover p i) = Leftover (go p) i
go (NeedInput x y) = NeedInput (go . x) (go . y)
go (HaveOutput p f o) = HaveOutput (go p) (runM f) o -- ERROR
in go (c0 Done)
foo :: Monad m => ConduitM i o (forall s. STT s m) r -> ConduitM i o m r
foo = threadSTT STT.runST
有人能谈谈这个吗?我真的很喜欢它的工作,但如果我不能那么我需要放弃使用 Data.Array.ST
来编写我的管道。
您似乎重新发明了 ConduitM
的 MFunctor
实例。您可以查看 source code.
管道包的作者,monad hoist in this style gives surprising results when you try to unwrap a monad with side effect。在你的情况下 runST
将被多次调用,因此每次管道产生一个项目时都会抛出状态。
您最好提升从 Conduit i o m r
到 Conduit i o (STT s m) r
线上的所有其他导管,然后在结果上调用 runST
。就像 transPipe lift
.
一样简单
我一直在尝试编写函数的实现:
foo :: Monad m => ConduitM i o (forall s. STT s m) r -> ConduitM i o m r
但我每次都因错误而失败:
Couldn't match type because variable `s` would escape its scope.
我现在怀疑实现这个功能是不可能的。
threadSTT :: Monad m
=> (forall a. (forall s. STT s m a) -> m a)
-> ConduitM i o (forall s. STT s m) r
-> ConduitM i o m r
threadSTT runM (ConduitM c0) =
ConduitM $ \rest ->
let go (Done r) = rest r
go (PipeM mp) = PipeM $ do
r <- runM mp -- ERROR
return $ go r
go (Leftover p i) = Leftover (go p) i
go (NeedInput x y) = NeedInput (go . x) (go . y)
go (HaveOutput p f o) = HaveOutput (go p) (runM f) o -- ERROR
in go (c0 Done)
foo :: Monad m => ConduitM i o (forall s. STT s m) r -> ConduitM i o m r
foo = threadSTT STT.runST
有人能谈谈这个吗?我真的很喜欢它的工作,但如果我不能那么我需要放弃使用 Data.Array.ST
来编写我的管道。
您似乎重新发明了 ConduitM
的 MFunctor
实例。您可以查看 source code.
管道包的作者,monad hoist in this style gives surprising results when you try to unwrap a monad with side effect。在你的情况下 runST
将被多次调用,因此每次管道产生一个项目时都会抛出状态。
您最好提升从 Conduit i o m r
到 Conduit i o (STT s m) r
线上的所有其他导管,然后在结果上调用 runST
。就像 transPipe lift
.