У вас возникли проблемы, потому что написанные вами «внутренние» типы подписей не означают, что они выглядят как бы это значило. В частности, ваше использование c
не соответствует друг другу, а не a
в верхней подписи, и они должны. Haskell жалуется, что эти «жестко определенные» переменные типа, несмотря на переменные, не могут быть одинаковыми, но поскольку они основаны на «жестком» выборе того, что a
... они должны!
Вы можете сделать GHC (но не Haskell в целом) ведут себя так, как вы хотите с расширением под названием {-# LANGUAGE ScopedTypeVariables #-}
, где ваш код становится
{-# LANGUAGE ScopedTypeVariables #-}
rearrange :: forall a . [Int] -> [a] -> [a]
rearrange l la = elems (f 1 posarr)
where
b = length l
listarr :: Array Int Int
listarr = listArray (1, b) l
arra :: Array Int a
arra = listArray (1,b) la
posarr :: Array Int a
posarr listArray (1,b) la
f i posarr
| (b < i) = posarr
| otherwise = f (i+1) (posarr // [(listarr!i,arra!i)])
Обратите внимание, что все, что я сделал добавить явный forall
и изменено некоторые c
переменные до a
. Что делать ScopedTypeVariables
позволяет вводить области переменных типа с помощью forall
, где любые подписи типов в коде, которые отступы под таким явным знаком forall
'd, могут повторно использовать имена переменных типа, введенные в этом forall
, и иметь их в точности.
Что может иметь смысл при рассмотрении того, как Haskell интерпретирует сигнатуры типов без расширения. В частности, существует неявное forall
перед тем каждый тип подписи
-- is actually
foo :: [a] -> [a] -> [a] foo :: forall a. [a] -> [a] -> [a]
foo xs ys = it where foo xs ys = it where
it :: [a] it :: forall a. [a]
it = xs ++ ys it = xs ++ ys
Что заставляет a
переменной в каждой из этих подписей типа быть разными и, таким образом, этот фрагмент кода не может компилироваться, так как он действует только тогда, когда те, два a
s одинаковы. С ScopedTypeVariables
мы имеем
foo :: forall a . [a] -> [a] -> [a]
foo xs ys = it where
it :: [a]
it = xs ++ ys
, где внутренняя область видимости сигнатура-х a
означает точно такой же, как и в a
внешней подписи х.
Является ли следующий код компиляцией без ошибок. я сделал то же самое, что и вы, но это говорит что-то вроде этого: «Незаконный символ». в типе Возможно, вы указали -XRanktype или аналогичный флаг, чтобы включить явный forall ........ Но одна вещь, которую я использую Ubuntu и компиляция с использованием терминала, также вызывает некоторую ошибку. – supernova
Чтобы включить 'forall', вы должны использовать расширение' ScopedTypeVariables'. 'RankNTypes' - это совершенно другое расширение. Оба они зависят от и автоматически помещают расширение «ExplicitForalls», которое вы также можете выбрать отдельно, если хотите, хотя оно не имеет семантических преимуществ. –
Если вы используете GHCi, вы можете установить эти флаги на лету, как ': set -XScopedTypeVariables' –