【发布时间】:2016-02-07 03:29:44
【问题描述】:
我一直在尝试编写函数的实现:
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 i o (forall s. STT s m) r -> ConduitM i o m r类型被称为不可预测类型,因为在类型构造函数(在这种情况下为ConduitM)内部有一个forall。在存在不可预测类型的情况下,类型推断会彻底失败(出于理论和实践原因)。您可以通过使用类型签名注释 everything 或为量化类型定义新类型来解决此问题:newtype X m = X (forall s . STT s m)然后foo :: ConduitM i o (X m) r -> ...。 -
为什么不直接实现
foo :: ConduitM i o (STT s m) r -> ConduitM i o m r呢?
标签: haskell monad-transformers conduit st-monad