在 where 子句中键入签名
我编写了一个类似于 Data.Enumerator.List.map 的函数,它使 Iteratee
与提供不同 Enumerator
兼容>流类型。
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
如果我省略 go
的类型签名,这将工作得很好。 但是,我想包含它,但我无法确定正确的签名应该是什么。 我认为应该是这样的:
go :: Monad m =>步骤ai mb-> Iteratee ao m b
但这不起作用。
我需要一些关于为 go
找到正确类型签名的建议。
I've written a function similar to Data.Enumerator.List.map
that makes an Iteratee
compatible with an Enumerator
that feeds a different Stream
type.
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
If I omit the type signature for go
, this will work just fine.
However, I'd like to include it but I'm unable to determine what the correct signature should be.
Here's what I think it should be:
go :: Monad m => Step ai m b -> Iteratee ao m b
but that doesn't work.
I need some advice on finding the correct type signature for go
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
您可能无法按原样为
go
提供类型签名。这样做的原因是它利用了
test
绑定的多态参数。这意味着,在go
内部,标识符f
的类型为(ao -> ai)
,用于一些特定但未知的< /em> 类型ao
和ai
。类型变量通常仅在引入它们的单个类型签名的范围内,因此当您为
go
提供其自己的类型签名时,ao
和ai< /code> 有新的多态类型,当尝试将它们与
test
签名中名称相似但固定(且不可知)的类型组合时,这当然会导致类型错误。最终的结果是你无法显式地写出
go
的类型,这不是很令人满意。为了解决这个问题,GHC 提供了 ScopedTypeVariables 扩展,它允许将类型签名中引入的变量引入函数的where
子句中的范围内。请注意,如果您仅使用
where
子句来创建定义的内部作用域,并且不使用由参数绑定到外部函数的标识符,则可以在中编写类型签名where
子句就像顶级绑定一样。如果你不想使用GHC扩展,你可以简单地冗余地传递参数。在这种情况下,类似这样的事情应该起作用:You probably can't give
go
a type signature as-is.The reason for this is that it makes use of polymorphic arguments bound by
test
. This means that, insidego
, the identifierf
has type(ao -> ai)
for some specific, but unknown typesao
andai
.Type variables are generally only in scope for the single type signature where they're introduced, so when you give
go
its own type signature, theao
andai
there are new, polymorphic types, which of course causes a type error when trying to combine them with the similarly named, but fixed (and unknowable) types fromtest
's signature.The end result is that you can't write the type of
go
explicitly, which is not very satisfying. To solve this, GHC offers the ScopedTypeVariables extension, which allows bringing variables introduced in a type signature in scope inside thewhere
clause of the function, among other things.Note that if you only use the
where
clause to create an internal scope for definitions, and don't make use of identifiers bound by arguments to the outer function, you can write type signatures in thewhere
clause just like you can for top level bindings. If you don't want to use GHC extensions, you can simply pass the parameters in redundantly. Something like this should work in that case:您可能需要该类型,但启用了
ScopedTypeVariables
扩展,并在范围内使用test
类型签名中的变量:请参阅 GHC 文档了解更多信息。
You probably want that type, but with the
ScopedTypeVariables
extension enabled and with the variables fromtest
's type signature in scope:See the GHC documentation for more information.