2 级类型和函数组合的类型错误 [英] Type error with rank-2 types and function composition

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

问题描述

以下是一些编译指示和一些导入:

Here are some pragmas and some imports:

{-# LANGUAGE ScopedTypeVariables #-}

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

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

Now here's my problem. The following code typechecks:

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

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

However, when I replace the $ with composition:

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) }

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

What's werid is, if I give the function composition its own name, then it typechecks again:

elemSTArray = elems . runSTArray

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

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

I'm not sure what's going on here. I would expect the second piece of code to typecheck nicely. And I don't understand why it typechecks again if I give the composed function its own name.

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

This is a simplified version of some code that I had that broke when upgrading from GHC 6.2 to 7 and I'm trying to understand why this happens now. Thanks for helping!

推荐答案

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

As you already hint at in the title of your post, the problem has to do with runSTArray having a polymorphic type of rank 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需要用a实例化多态类型而不是单态类型.这需要所谓的不可预测的多态性.Dimitrios Vytiniotis、Stephanie Weirich 和 Simon Peyton Jones 在 ICFP 2008 论文中解释了 GHC 如何实现不可预测的多态性:FPH:Haskell 的一流多态性.最重要的是,虽然 FPH 经常为您提供您期望的行为,但有时在您在问题中描述的简单转换下无法保留可键入性:请参阅上述论文的第 6.2 节.

writing runSTArray $ ... means that the type variable a in the type schema of ($) needs to be instantiated with a polymorphic type rather than a monomorphic type. This requires so-called impredicative polymorphism. How GHC implements impredicative polymorphism is explained in the ICFP 2008 paper by Dimitrios Vytiniotis, Stephanie Weirich, and Simon Peyton Jones: FPH : First-class Polymorphism for Haskell. The bottom line is that while FPH often gives you the behaviour that you expect, typeability is sometimes not preserved under simple transformations like the ones you describe in your question: see Section 6.2 of the aforementioned paper.

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

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