对STArray进行MArray专业化

时间:2012-12-22 21:49:05

标签: haskell marray

我很担心在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的类型吗?

谢谢!

2 个答案:

答案 0 :(得分:3)

  

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

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

不完全,STArray s由状态类型参数化,因此它是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扩展名,因为现在您需要从a的签名中引用实例化类型变量doSomething的类型。不过,我发现它比行中间的表达式类型签名更具可读性。

答案 1 :(得分:0)

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

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

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

如果我是对的,你可以通过在thawData或创建它的表达式上添加类型注释来修改xArr,从而指定什么类型{{1}应该是。