Первое замечание: сообщение об ошибке говорит о том, что отсутствует объявление экземпляра, а не неизвестное имя переменнойКроме того, в качестве первой подсказки обратите внимание, что сообщение об ошибке содержит два различных тега ST
: s
, возникающих из STUArray
(что связано с параметром arr
вашей функции), и еще один s1
in ST s1
.Откуда это s1
?Действительно, в вашей программе об этом нет упоминания!
В качестве второго совета попробуйте удалить объявление подписи для readArr
, чтобы предложение where
выглядело как
where
readArr = readArray arr 0
Вдруг этот тип проверяет и работает просто отлично.Что происходит?
Ответ таков: когда вы писали readArr :: ST s Int
, вы имели в виду s
из сигнатуры checkArr
, но правила области видимости таковы, что фактически вводится новая переменная типа, котораяПроверщик типов переименовывает вас в s1
, а s
не обязательно совпадает с s1
, следовательно, ошибка типа.Если вы пропустите эту сигнатуру, то средство проверки типов сможет получить правильный тип.
Если вы действительно хотите записать тип в where
-привязку, как это, есть расширение для этого!ScopedTypeVariables
позволяет вам ссылаться на свободную переменную (которая является сигнатурой s
из checkArr
) внутри функции.Итак, добавьте {-# LANGUAGE ScopedTypeVariables #-}
и сообщите контролеру типов, что вы хотите его ограничить, написав явный forall
в сигнатуре верхнего уровня: checkArr :: forall s. STUArray s Int Int -> ST s Bool
.После этого ваш код будет проверен.