3

我对在 Haskell 中使用多态性的 STArray 感到困惑。

假设我有以下设置

data SomeData a = Something a

thawData :: MArray u a m => SomeData a -> m (u Int a)
thawData = {- doesn't matter -}

doSomething :: SomeData a -> ()
doSomething x = runST $ do 
  xArr <- thawData x
  return ()

现在,我相信 thawData 的类型专门用于这种情况

thawData :: SomeData a -> ST s (STArray Int a)

但是,除非我将 thawData 的类型更改为显式使用 STArray,否则即使我尝试在 do 表达式的主体中显式键入它,这也不会编译。

那么到底发生了什么?为什么类型不能专门化?
我可以以某种方式更改 doSomething 的主体而不是 thawData 的类型吗?

谢谢!

4

2 回答 2

3

现在,我相信 thawData 的类型专门用于这种情况

thawData :: SomeData a -> ST s (STArray Int a)

不完全是,STArrays 由状态类型参数化,所以它是ST s (STArray s Int a). 但这无法推断,因为错误消息告诉您:

Thaw.hs:13:11:
    No instance for (MArray u0 a (ST s))
      arising from a use of `thawData'
    The type variable `u0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s)
    Note: there are several potential instances:
      instance MArray (GHC.Arr.STArray s) e (ST s)
        -- Defined in `Data.Array.Base'
      instance MArray (Data.Array.Base.STUArray s) Bool (ST s)
        -- Defined in `Data.Array.Base'
      instance MArray (Data.Array.Base.STUArray s) Char (ST s)
        -- Defined in `Data.Array.Base'
      ...plus 15 others
    Possible fix: add an instance declaration for (MArray u0 a (ST s))
    In a stmt of a 'do' block: xArr <- thawData x

有几个可能的MArray类实例ST s作为 monad 可供选择(即使只有一个实例在范围内,编译器也会在开放世界假设下运行,其他实例可以在其他地方定义)。所以编译器不知道要使用哪个实例,因此它拒绝编译代码。

现在,建议的可能修复在这里不正确,您需要通过另一种方式修复数组类型。thawData一种可能性是像您一样在顶层专门化类型签名。

另一种是专攻它doSomething

doSomething :: SomeData a -> ()
doSomething x = runST $ do 
  xArr <- (thawData :: SomeData b -> ST s (STArray s Int b)) x
  return ()

它告诉编译器在thawData这里使用哪种类型,第三个是将表达式类型签名移动到该行的末尾

{-# LANGUAGE ScopedTypeVariables #-}
-- imports etc.

doSomething :: forall a. SomeData a -> ()
doSomething x = runST $ do 
  xArr <- thawData x :: ST s (STArray s Int a)
  return ()

但这需要ScopedTypeVariables扩展,因为现在您需要引用adoSomething. 不过,我发现它比行中间的表达式类型签名更具可读性。

于 2012-12-22T23:18:06.710 回答
0

如果您包含错误消息,它会有所帮助。

事实上,我所能做的就是猜测错误是因为您没有提供足够的上下文来确定xArr. 特别是,m可以与参数类型统一ST sa来自参数类型,但没有确定的上下文u

我的猜测是编译器告诉你的错误,但由于你没有包含它,这只是一个猜测。

如果我是对的,您可以thawData通过在类型注释上xArr或创建它的表达式上进行修改来解决此问题,从而指定u应该是什么类型。

于 2012-12-22T22:42:21.660 回答