Вот что происходит: uncons
должен работать в какой-то монаде. Вы можете увидеть это по типу подписи: uncons :: Stream s m t => s -> m (Maybe (t, s))
. Но вы просто делаете let x = uncons i
- так что x
- это вычисление monadi c, которое возвращает результат uncons i
, но вы не указали , который monad в этом вычислении monadi c работает внутри. Вы случайно знаете, что вы 'хотите' uncons i
бежать внутри вашей монады m
(что удовлетворяет Stream s m Char
), но GH C не знает этого. Итак, GH C делает предположение, что здесь uncons i :: m0 (Maybe (t, s))
, где m0
- произвольная монада. Таким образом, GH C создает ошибку, которую вы видите, поскольку uncons
требует, чтобы ограничение Stream s m0 Char
было выполнено, чтобы использовать его, но это ограничение не обязательно выполняется для любого случайного m0
.
Как это можно решить? Ну, вы уже знаете, что все эти вычисления имеют тип ParsecT s (ShiftedState u s) m Char
, а m
удовлетворяет экземпляру Stream s m Char
. И, как выясняется, есть функция lift :: Monad m => m a -> ParsecT s u m a
, которая «поднимает» вычисление monadi c m a
до вычисления Parse c ParsecT s u m a
. Таким образом, вы можете просто переписать свою функцию следующим образом:
myParser :: (Stream s m Char) => ParsecT s (ShiftedState u s) m String
myParser = do
s <- P.getParserState
let i = stateInput s
x <- lift (uncons i)
return ""
Я не проверял ее, но это должно работать, если я не допустил ошибок.
(Другое решение состоит в том, чтобы просто дать x
сигнатуру типа:
let x :: m (Maybe (Char, s))
x = uncons i
Это заставит x
иметь нужный вам тип. Теперь GH C может посмотреть и увидеть, что m
и s
все удовлетворяют соответствующим ограничение, поэтому не приводит к этой ошибке. Но для компиляции требуется расширение языка ScopedTypeVariables
, и оно гораздо менее элегантно, чем в предыдущем решении.)