Продолжайте получать (используйте FlexibleContexts, чтобы разрешить это) Ошибка в простой функции Haskell
Я просто играю с монадами на Haskell и получаю сообщение об ошибке, которое не могу исправить. Мой сегмент кода использует состояние Monad, чтобы сложить вместе первые два символа из строки и вернуть их как часть состояния. Моя строка "put" продолжает давать мне ошибку:
* Non type-variable argument in the constraint: MonadState [a] m
(Use FlexibleContexts to permit this)
* When checking the inferred type
testH :: forall (m :: * -> *) a. MonadState [a] m => [a] -> m [a]
Как я могу это исправить? Расширение языка не вариант, мне просто нужно знать, как я могу изменить свой код, чтобы заставить его работать
test xs =
runState (testH (tail xs)) ((head xs):[])
testH xs =
do
a <- get
put ((head xs):a)
b <- get
return b
1 ответ
Вы можете решить эту проблему, включив FlexibleContexts
как это предлагается, или путем изменения вашей функции, чтобы работать на что-то более общее, чем списки.
Проблема в том, что Haskell не допускает переменные не-типа в контексте. Если вы напишите типы ваших функций (которые вы должны делать в любом случае), вы получите
testH :: (Monad m,MonadState [a] m) => [a] -> m [a]
это означает, что это функция, которая принимает список значений и возвращает действие в некоторой монаде, которая имеет возможность сохранять состояние списка значений того же типа, что и входные данные. К сожалению, [a]
бит в контексте недопустим в Haskell, потому что он имеет переменную не типового типа (а именно конструктор типа списка).
Лучшее решение здесь - просто включить расширение, которое допускает не типизированные переменные в контекстах. Это не опасно, просто расслабляет стандарт. На самом деле, многопараметрические классы типов (такие как MonadState
) не действительны на Haskell, поэтому вы уже используете языковые расширения, нравится вам это или нет.
Если это действительно не вариант, вы можете изменить его на (Monad m,SomeTypeclass f,MonadState (f a) m)
и переписать ваши функции для работы с любым конструктором, который следует за SomeTypeclass
на ваш выбор. Это удаляет конструктор типа списка из типа и позволяет коду работать без FlexibleContexts
,