这里有一些pragma和一些导入:
{-# LANGUAGE ScopedTypeVariables #-}
import Control.Monad.ST
import Data.Array.ST
import Data.Array
Run Code Online (Sandbox Code Playgroud)
现在这是我的问题.以下代码类型检查:
foo :: forall a. a -> [a]
foo x = elems $ runSTArray $ do
newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)
Run Code Online (Sandbox Code Playgroud)
但是,当我更换$组合物时:
foo :: forall a. a -> [a]
foo x = elems . runSTArray $ do
newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
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) }
Run Code Online (Sandbox Code Playgroud)
令人担忧的是,如果我给函数组合赋予自己的名字,那么它再次进行类型检查:
elemSTArray = elems . runSTArray
foo :: forall a. a -> [a]
foo x = elemSTArray $ do
newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int a)
Run Code Online (Sandbox Code Playgroud)
我不确定这里发生了什么.我希望第二段代码可以很好地进行类型检查.如果我给这个组合函数赋予它自己的名字,我不明白为什么它会再次出现问题.
这是我从GHC 6.2升级到7时遇到的一些代码的简化版本,我试图理解为什么会发生这种情况.谢谢你的帮助!
Ste*_*ans 15
正如您在帖子的标题中暗示的那样,问题与runSTArray具有等级2的多态类型有关.
runSTArray :: Ix i => (forall s. ST s (STArray s i e)) -> Array i e
Run Code Online (Sandbox Code Playgroud)
同
elems :: Ix i => Array i e -> [e]
Run Code Online (Sandbox Code Playgroud)
和
($) :: (a -> b) -> a -> b
Run Code Online (Sandbox Code Playgroud)
写入runSTArray $ ...意味着a类型模式中的类型变量($)需要使用多态类型而不是单态类型进行实例化.这需要所谓的不可预测的多态性.在Dimitrios Vytiniotis,Stephanie Weirich和Simon Peyton Jones的ICFP 2008论文中解释了GHC如何实现不可预测的多态性:FPH:Haskell的一流多态性.最重要的是,尽管FPH通常会为您提供您期望的行为,但有时候不会像您在问题中描述的简单转换那样保留可打字性:请参阅上述文章的第6.2节.
斯特凡打我的答案-棘手的一点是,它不是$VS .之间elems以及runSTArray这是个问题-它的$下面runSTArray.由于something $ rankNthing是如此常见,有一个聪明的位(我忘了细节),试图让你这样做作为一个角落案件.但不知何故使用早期的组合可以防止这种情况发生 问题的位置通过以下事实证明:
foo x = (elems . runSTArray) (
(newListArray (1,10) (replicate 10 x) :: ST s (STArray s Int String)))
Run Code Online (Sandbox Code Playgroud)
我不确定这本身就是一个bug,但它肯定是一个值得创建故障的意外行为,因为可能仍有更好的算法来捕获像你提供的那样的案例.