首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >rank-2类型和函数组合的类型错误

rank-2类型和函数组合的类型错误
EN

Stack Overflow用户
提问于 2011-12-01 22:50:10
回答 2查看 479关注 0票数 17

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

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

werid的意思是,如果我给函数组合起了自己的名字,那么它就会再次检查类型:

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时的一些代码的简化版本,我正在试图理解为什么现在会发生这种情况。感谢您的帮助!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2011-12-01 23:36:37

正如你已经在你的文章标题中暗示的那样,这个问题与具有等级2的多态类型的runSTArray有关。

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撰写的ICFP2008论文中解释了GHC如何实现不可预测的多态性:FPH : First-class Polymorphism for Haskell。底线是,虽然FPH通常会提供您所期望的行为,但有时在您的问题中描述的简单转换下不会保留可打印性:请参阅前述论文的6.2节。

票数 15
EN

Stack Overflow用户

发布于 2011-12-02 00:00:54

Stefan先我一步找到了答案--棘手的一点是,问题不是elemsrunSTArray之间的$.之间的竞争--而是runSTArray之后的$。由于something $ rankNthing是如此常见,这里有一个聪明的小技巧(我忘记细节了),它试图让你把它当作一个绝佳的例子。但不知何故,使用早期的组合可以防止这一点。问题的位置由以下类型检查的事实来证明:

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

我不确定这本身就是一个bug,但它肯定是一个意想不到的行为,值得为它创建一个罚单,因为可能仍然有更好的算法来捕获像您提供的案例。

票数 9
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/8343239

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档