Вот простой пример использования haskeline с преобразователем StateT
для создания цикла команд ввода с отслеживанием состояния:
{-# LANGUAGE NoMonomorphismRestriction #-}
{-# LANGUAGE FlexibleContexts #-}
import Control.Monad.State.Strict
import Control.Monad.Trans (lift)
import System.Console.Haskeline
main = runStateT (runInputT defaultSettings loop) ""
check ma b fb = maybe b fb ma
commands :: (MonadState String m, MonadIO m) => [(String, [String] -> InputT m ())]
commands = [ ("set", performSet), ("get", performGet) ]
performSet args = lift $ put (head args)
performGet _ = do v <- lift get; outputStrLn $ "v = " ++ show v
loop :: (MonadException m, MonadState String m) => InputT m ()
loop = do
minput <- getInputLine "% "
check minput (return ()) $ \inp -> do
let args = words inp
case args of
[] -> loop
(arg0:argv) -> do
case lookup arg0 commands of
Nothing -> do outputStrLn "huh?"; loop
Just handler -> do handler argv; loop
Список commands
содержит все распознанные команды - пары (имя, обработчик). Я хочу получить список имен, используя выражение вроде:
commandNames = map fst commands
но средство проверки типов жалуется на «Нет экземпляра для (MonadState String m0) из-за использования« команд »- переменная типа« m0 »неоднозначна ...»
Что мне нужно сделать, чтобы удовлетворить проверку типов?