MArray специализация для STArray

Я запутался в использовании STArray в Haskell с полиморфизмом.

Предположим, у меня есть следующие настройки

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 ответа

Решение

Теперь я считаю, что тип 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 в качестве монады на выбор (и даже если в области действия находился только один экземпляр, компилятор работает в предположении открытого мира, другие экземпляры могут быть определены где-то еще). Таким образом, компилятор не знает, какой экземпляр использовать, поэтому он отказывается компилировать код.

Теперь предлагаемое возможное исправление не является правильным, вам нужно исправить тип массива другим способом. Одна возможность состоит в том, чтобы специализировать тип подписи 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, Я нахожу это более читабельным, чем подпись типа выражения в середине строки.

Если вы включите сообщение об ошибке, это поможет.

На самом деле, все, что я могу сделать, это предположить, что ошибка в том, что вы не предоставляете достаточно контекста для определения типа xArr, Особенно, m может быть объединен с ST s а также a исходит из типа аргумента, но нет контекста для определения u,

Я предполагаю, что это ошибка, о которой вам говорит компилятор, но поскольку вы ее не включили, это всего лишь предположение.

Если я прав, вы можете решить это без изменения thawData поместив аннотацию типа на xArr или выражение, которое его создает, таким образом, чтобы указать, какой тип u должно быть.

Другие вопросы по тегам