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