Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell runST与函数组合_Haskell_Function Composition - Fatal编程技术网

Haskell runST与函数组合

Haskell runST与函数组合,haskell,function-composition,Haskell,Function Composition,为什么要进行这种类型检查: runST $ return $ True 但以下情况并非如此: runST . return $ True GHCI投诉: 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

为什么要进行这种类型检查:

runST $ return $ True
但以下情况并非如此:

runST . return $ True
GHCI投诉:

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

runST$do{…}
模式非常常见,而且它通常不会进行类型检查这一事实非常烦人,以至于GHC包含了一些特定于
ST
的类型检查技巧以使其正常工作。这些黑客可能在这里攻击
($)
版本,但不是
()
版本。

这些信息有点混淆了重点(或者我觉得是这样)。 让我重写你的代码:

runST (return True)   -- return True is ST s Bool
(runST . return) True  -- cannot work

另一种说法是,单态的
m0a0
(返回的结果,如果它将得到a0)不能与(对于所有的s.stsa)统一起来。

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

> :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
如果我们用自己的版本替换
($)
,您的第一个示例也会出现同样的问题:

> 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)'
这里发生的是,GHC 7中有一个特殊的键入规则,它只适用于标准的
($)
运算符。西蒙·佩顿·琼斯在以下文章中解释了这种行为:

这是一个类型推断的激励示例,可以处理 非指示性类型。考虑<代码>($)<代码>:

在这个例子中,我们需要用
(对于所有s.ST SA)
实例化
p
,这就是 非指示多态性意味着:用 多态型

遗憾的是,据我所知,没有一个具有合理复杂性的系统能够进行打字检查 [这]没有帮助。有很多复杂的系统,我有 我曾与他人合作撰写过至少两篇论文,但都太多了 在GHC生活真是太复杂了。我们确实实施了 boxy类型,但我在实现新的typechecker时去掉了它。 没人明白

然而,人们经常写作

runST $ do ... 
在GHC7中,我实现了一个特殊的键入规则,仅用于
($)
的中缀使用。只要把
(f$x)
想象成一个新的 语法形式,有明显的打字规则,然后你就可以走了


您的第二个示例失败,因为对于
()

没有这样的规则,这会执行类型检查:
unsafePerformIO。return$True
@Ingo:您对这两个示例的分析是错误的
runST$return$True
($)runST(($)return True)
,并且
runST。return$True
($)(.runST return)True
。如果没有排名2的类型,他们也会做同样的事情。@ehird-你说得对,我忘了点。(嘿,那押韵…)谢谢,现在开始有意义了。有趣的一点。只要看到($)应用于2个参数,就可以直接删除($)。用一个与($)相同的自定义函数替换它应该很容易验证,然后看看类型检查器是否会抱怨。@Ingo:Yep,
让app fx=fx在runST`app`(return`app`True)
无法进行类型检查。有趣。@Hammar:这意味着,GHC显然放弃了$,尽管这对于更高级别的类型并不完全正确。这是正确的答案。第一个代码段通常不会进行类型检查,但是,GHC对
runST$whatever
有一个特殊规则,但对
runST没有特殊规则。如果
($)
可以作为
($):为所有(a:*)(b:a->*)提供独立键入的签名,则不会对其执行类型检查。((x:a)->bx)->(x:a)->bx
它在没有GHC技巧的情况下也能工作,对于
()
也同样如此。
($) :: forall p q. (p -> q) -> p -> q
runST $ do ...