runST和函数组成 [英] runST and function composition

查看:122
本文介绍了runST和函数组成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么这种类型检查:

  runST $ return $ True 

虽然以下内容不适用:

  runST。返回$ True 

GHCI抱怨:

 无法匹配预期的类型`forall s。 ST s c0'
,实际类型为`m0 a0'
预期类型:a0 - > forall s。 ST s c0
实际类型:a0 - > m0 a0
在'(。)'的第二个参数中,即'return'
在表达式:runST中。返回


解决方案

简短的回答是,类型推断不会总是使用更高级的类型。在这种情况下,它无法推断(。)的类型,但它会检查我们是否添加显式类型注释:

 > :m + Control.Monad.ST 
> :set -XRankNTypes
> :(((。)::((s0.ST s0a) - > a) - >(a→forall s1.ST s1a) - > a-> a)runST return) (a)→(a→a)→a→a→a→a→a→a→a→a→b→ )runST返回)$ True :: Bool

第一个例子也会出现同样的问题,如果我们用我们自己的版本替换($)

 > let app f x = f x 
> :t runST`app`(return`app` True)
< interactive>:1:14:
无法匹配期望的类型`forall s。 ST s t0'
,实际类型为`m0 t10'
预期类型:t10 - > forall s。 ST s t0
实际类型:t10 - > m0 t10
'app'的第一个参数,即'return'
在'app'的第二个参数中,也就是`(return`app` True)'

$ b

同样,这可以通过添加类型注释来解决:

 > :(app s :: a()s(s0。ST s0 a) - > a) - >(s1。ST s1 a) - > a)runST(返回`app` True)
(app ::((全部s0。ST s0 a) - > a) - >(全部s1 .ST s1 a) - > a)runST(返回`app` True):: Bool

这里发生的是GHC 7中有一个特殊的输入规则,它只适用于标准的( $)运算符。 Simon Peyton-Jones在 GHC用户邮件列表上的回复中解释了这种行为。 a>:


这是类型推断的一个激励性示例,可以处理
impandicative类型。考虑($)的类型:

 ($)::全部p q。 (p→q)→> p  - > q 

在这个例子中,我们需要实例化 p with (forall s。st sa),这就是
impandicative多态性的含义:用
多态类型实例化一个类型变量。


不幸的是,我知道没有合理复杂的系统可以单独检测
[this]。有很多复杂的系统,而且我有
在论文中至少有两个合作作者,但他们都是太多
Jolly复杂地生活在GHC中。我们确实有一个
boxy类型的实现,但是在实现新的类型检查器时我将它拿出来了。
没有人理解它。

然而,人们经常写作

  runST $ do ... 

在GHC 7中,我实现了一个特殊的输入规则,用于($)的中缀用途。只要将(f $ x)作为一个新的
语法形式,使用明显的键入规则,就可以离开了。


第二个例子失败是因为(。)没有这样的规则。


Why does this typecheck:

runST $ return $ True

While the following does not:

runST . return $ True

GHCI complains:

Couldn't match expected type `forall s. ST s c0'
            with actual type `m0 a0'
Expected type: a0 -> forall s. ST s c0
  Actual type: a0 -> m0 a0
In the second argument of `(.)', namely `return'
In the expression: runST . return

解决方案

The short answer is that type inference doesn't always work with higher-rank types. In this case, it is unable to infer the type of (.), but it type checks if we add an explicit type annotation:

> :m + Control.Monad.ST
> :set -XRankNTypes
> :t (((.) :: ((forall s0. ST s0 a) -> a) -> (a -> forall s1. ST s1 a) -> a -> a) runST return) $ True
(((.) :: ((forall s0. ST s0 a) -> a) -> (a -> forall s1. ST s1 a) -> a -> a) runST return) $ True :: Bool

The same problem also happens with your first example, if we replace ($) with our own version:

> let app f x = f x
> :t runST `app` (return `app` True)
<interactive>:1:14:
    Couldn't match expected type `forall s. ST s t0'
                with actual type `m0 t10'
    Expected type: t10 -> forall s. ST s t0
      Actual type: t10 -> m0 t10
    In the first argument of `app', namely `return'
    In the second argument of `app', namely `(return `app` True)'

Again, this can be solved by adding type annotations:

> :t (app :: ((forall s0. ST s0 a) -> a) -> (forall s1. ST s1 a) -> a) runST (return `app` True)
(app :: ((forall s0. ST s0 a) -> a) -> (forall s1. ST s1 a) -> a) runST (return `app` True) :: Bool

What is happening here is that there is a special typing rule in GHC 7 which only applies to the standard ($) operator. Simon Peyton-Jones explains this behavior in a reply on the GHC users mailing list:

This is a motivating example for type inference that can deal with impredicative types. Consider the type of ($):

($) :: forall p q. (p -> q) -> p -> q

In the example we need to instantiate p with (forall s. ST s a), and that's what impredicative polymorphism means: instantiating a type variable with a polymorphic type.

Sadly, I know of no system of reasonable complexity that can typecheck [this] unaided. There are plenty of complicated systems, and I have been a co-author on papers on at least two, but they are all Too Jolly Complicated to live in GHC. We did have an implementation of boxy types, but I took it out when implementing the new typechecker. Nobody understood it.

However, people so often write

runST $ do ... 

that in GHC 7 I implemented a special typing rule, just for infix uses of ($). Just think of (f $ x) as a new syntactic form, with the obvious typing rule, and away you go.

Your second example fails because there is no such rule for (.).

这篇关于runST和函数组成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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