【问题标题】:Type error with rank-2 types and function composition具有 rank-2 类型和函数组合的类型错误
【发布时间】:2012-01-10 17:02:07
【问题描述】:

这里有一些 pragma 和一些导入:

{-# LANGUAGE ScopedTypeVariables #-}

import Control.Monad.ST
import Data.Array.ST
import Data.Array

现在这是我的问题。以下代码类型检查:

foo :: forall a. a -> [a]
foo x = elems $ runSTArray $ do
    newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)

但是,当我用组合替换 $ 时:

foo :: forall a. a -> [a]
foo x = elems . runSTArray $ do
    newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)

我收到此错误:

Couldn't match expected type `forall s. ST s (STArray s i0 e0)'
            with actual type `ST s0 (STArray s0 Int a)'
In the expression:
    newListArray (1, 10) (replicate 10 x) :: ST s (STArray s Int a)
In the second argument of `($)', namely
  `do { newListArray (1, 10) (replicate 10 x) ::
          ST s (STArray s Int a) }'
In the expression:
      elems . runSTArray
  $ do { newListArray (1, 10) (replicate 10 x) ::
           ST s (STArray s Int a) }

奇怪的是,如果我给函数组合起自己的名字,那么它会再次进行类型检查:

elemSTArray = elems . runSTArray

foo :: forall a. a -> [a]
foo x = elemSTArray $ do
    newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)

我不确定这里发生了什么。我希望第二段代码能够很好地进行类型检查。而且我不明白如果我给组合函数起自己的名字,为什么它会再次进行类型检查。

这是我从 GHC 6.2 升级到 7 时损坏的一些代码的简化版本,我试图了解为什么现在会发生这种情况。感谢您的帮助!

【问题讨论】:

  • 我并不是一个真正的 Haskell 程序员,但是组合相对于$ 的优先级是多少?如果将子表达式 elems . runSTArray 括起来会怎样?
  • 我无法使用 GHC 6.12.1 重现此内容。
  • Gian: $ 的优先级低于 .,所以如果我将子表达式括起来,它的行为是相同的。 opqdonut:这在 GHC 6.2 上也没有发生在我身上,但在 GHC 7.0.3 上发生了
  • @EEVIAC:哦,对不起,没明白升级的意思。绝对可以在 7 岁以下重现。您是否已经提交了 GHC 错误?
  • 不,我没有,因为我不确定这是一个错误,我只是认为这是我目前对类型系统的理解的错误,因为我没有关注近来GHC的发展。所以这是一个错误?

标签: haskell types


【解决方案1】:

Stefan 打败了我的答案——棘手的一点是,这不是elemsrunSTArray 之间的$. 这就是问题所在——而是$ 跟在runSTArray 之后。由于something $ rankNthing 很常见,所以有一个聪明的地方(我忘记了细节)试图让你在极端情况下这样做。但不知何故,早先使用该组合可以防止这种情况发生。问题的位置可以通过以下事实来证明:

foo x = (elems . runSTArray) (
    (newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int String)))

我不确定这本身是否是一个错误,但它肯定是一个值得创建票证的意外行为,因为可能仍有更好的算法来捕获像您提供的那样的案例。

【讨论】:

    【解决方案2】:

    正如您在帖子标题中已经暗示的那样,问题与 runSTArray 具有等级 2 的多态类型有关。

    runSTArray :: Ix i => (forall s. ST s (STArray s i e)) -> Array i e
    

    elems :: Ix i => Array i e -> [e]
    

    ($) :: (a -> b) -> a -> b
    

    runSTArray $ ...表示($)的类型模式中的类型变量a需要用多态类型而不是单态类型来实例化。这需要所谓的暗示性多态性。 Dimitrios Vytiniotis、Stephanie Weirich 和 Simon Peyton Jones 在 ICFP 2008 论文中解释了 GHC 如何实现暗示性多态性:FPH : First-class Polymorphism for Haskell。底线是,虽然 FPH 通常会为您提供您期望的行为,但在您在问题中描述的简单转换下,有时不会保留可类型性:请参阅上述论文的第 6.2 节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-12-15
      • 2020-09-01
      • 1970-01-01
      • 2013-05-10
      • 1970-01-01
      • 1970-01-01
      • 2018-09-21
      • 1970-01-01
      相关资源
      最近更新 更多