Я использую операционную монаду Генриха Апфельмуса. Я хотел бы параметризовать интерпретатор монадой для типа результата. Компилируется следующая версия моего кода:
{-# LANGUAGE GADTs #-}
import Control.Monad.Operational
data EloI a where
Display :: Int -> EloI ()
type Elo a = Program EloI a
interpret :: Monad m => (Int -> m ())
-> Elo a
-> Int
-> m a
interpret display = interp
where
interp :: Monad m => Elo a -> Int -> m a
interp = eval . view
eval :: Monad m => ProgramView EloI a -> Int -> m a
eval (Display i :>>= is) s = interp (is ()) s
Теперь я изменяю последнюю строку на
eval (Display i :>>= is) s = display i >> interp (is ()) s
, и вывод типа больше не выполняется, я получаю вывод
Не удалось вывести (m ~ m1) из контекста (Monad м)
связаны сигнатурой типа для интерпретации :: Monad m => (Int -> m ()) -> Elo a -> Int -> m a
(...)
Когда я удаляю подпись типа для interp, я получаю дополнительную ошибку (не удалось вывести (a1 ~ a)).
Когда я меняю все m на IO (как в примере с крестиками-ноликами для операционной монады), он снова компилируется.
Я пытаюсь сделать что-то, что не имеет смысла, или я могу подсказать GHC? Признаюсь, я не уверен, что мне нужна такая гибкость.