qub*_*tal 13 haskell enumerator parametric-polymorphism
我写了一个类似的函数,Data.Enumerator.List.map它Iteratee与Enumerator一个不同Stream类型的函数兼容.
import Data.Enumerator
test :: Monad m => (ao -> ai) -> Iteratee ai m b -> Iteratee ao m b
test f iter = go $$ iter
where go (Continue k) = continue $
\stream -> go $$ k (fmap f stream)
go (Yield res _) = yield res EOF
Run Code Online (Sandbox Code Playgroud)
如果我省略了类型签名go,这将工作得很好.但是,我想包括它,但我无法确定正确的签名应该是什么.这是我认为它应该是:
go :: Monad m => Step ai m b -> Iteratee ao m b
但这不起作用.
我需要一些关于找到正确类型签名的建议go.
C. *_*ann 14
您可能无法go按原样提供类型签名.
这样做的原因是它利用了绑定的多态参数test.这意味着,内部go,该标识符f的类型为(ao -> ai)对于一些特定的,但未知类型ao和ai.
类型变量一般只在范围上为他们介绍了在单一类型的签名,所以当你给go自己的类型签名中,ao并ai有新的,多态类型,这当然会导致一个类型错误尝试将它们与结合时类似命名,但来自test签名的固定(和不可知)类型.
最终的结果是你不能写go明确的类型,这不是很令人满意.为了解决这个问题,GHC提供了ScopedTypeVariables扩展,它允许将where函数子句中范围内的类型签名中引入的变量引入其中.
请注意,如果仅使用该where子句为定义创建内部作用域,并且不使用由外部函数的参数绑定的标识符,则可以在where子句中编写类型签名,就像使用顶级绑定一样.如果您不想使用GHC扩展,则只需冗余地传递参数即可.这样的事情应该适用于这种情况:
test :: Monad m => (ao -> ai) -> Iteratee ai m b -> Iteratee ao m b
test f iter = go f $$ iter
where go :: Monad m => (ao -> ai) -> Step ai m b -> Iteratee ao m b
go f (Continue k) = continue $
\stream -> go f $$ k (fmap f stream)
go _ (Yield res _) = yield res EOF
Run Code Online (Sandbox Code Playgroud)
您可能需要该类型,但ScopedTypeVariables启用了扩展并且test范围内的变量来自类型签名:
{-# LANGUAGE ScopedTypeVariables #-}
import Data.Enumerator
test :: forall m ai ao b. Monad m => (ao -> ai) -> Iteratee ai m b -> Iteratee ao m b
test f iter = go $$ iter
where go :: Step ai m b -> Iteratee ao m b
go (Continue k) = continue $
\stream -> go $$ k (fmap f stream)
go (Yield res _) = yield res EOF
Run Code Online (Sandbox Code Playgroud)
有关更多信息,请参阅GHC文档.