在where子句中键入签名 [英] Type signature in a where clause

查看:99
本文介绍了在where子句中键入签名的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个类似于 Data.Enumerator.List.map 的函数,它使得 Iteratee 与一个 Enumerator ,它提供了一个不同的 Stream 类型。



import Data.Enumerator

  test :: Monad m => (a 0  - > a 1) - > 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 m b - > Iteratee ao mb



但不起作用。

我需要一些建议来寻找正确的类型签名 go

解决方案

您可能无法给 go 一个类型签名原样。



原因是它使用由<$ c $绑定的多态参数C>测试。这意味着,在 go 中,标识符 f 的类型为(ao - > ai )用于某些特定但未知的类型 ao ai



类型变量通常只在引入它们的单一类型签名的范围内,所以当您给 go 自己的类型签名, ao ai 有新的多态类型,这当然会导致在尝试将它们与 test 的签名中的类似命名但固定(和不可知)类型结合时出现错误。



最终的结果是,你不能明确写出 go 的类型,这不是很令人满意。为了解决这个问题,GHC提供了 ScopedTypeVariables扩展,它允许在函数的 where 子句内的范围内引入类型签名中引入的变量,等等。



请注意,如果您仅使用其中子句为定义创建内部作用域,并且不使用标识符绑定到外部函数的参数,您可以在中写入类型签名,其中子句与顶级绑定相似。如果您不想使用GHC扩展,则只需简单地传递参数即可。这样的事情应该在这种情况下工作:

  test :: Monad m => (a 0  - > a 1) - > Iteratee ai m b  - > Iteratee ao m b 
test f iter = go f $$ iter
where go :: Monad m => (a 0 - > a 1) - >步骤ai m b - > Iteratee ao m b
go f(Continue k)= continue $
\stream - >去f $$ f(fmap f stream)
去_(Yield res _)= yield res EOF


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.

解决方案

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, inside go, the identifier f has type (ao -> ai) for some specific, but unknown types ao and ai.

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, the ao and ai 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 from test'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 the where 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 the where 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:

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

这篇关于在where子句中键入签名的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆