Используйте входные данные из ge tkeputLine Haskeline
У меня есть код
main :: IO()
main = runInputT defaultSettings loop
where
--loop :: InputT IO ()
loop = do
minput <- getInputLine "$ "
case minput of
Nothing -> return ()
Just input -> process $ words input
loop
Где процесс имеет определение типа
process :: [String] -> IO ()
Однако я получаю ошибку:
• Couldn't match type ‘IO’ with ‘InputT m’
Expected type: InputT m ()
Actual type: IO ()
• In the expression: process $ words input
In a case alternative: Just input -> process $ words input
In a stmt of a 'do' block:
case minput of {
Nothing -> return ()
Just input -> process $ words input }
Мне было интересно, если кто-нибудь может объяснить, что я делаю не так. Я просто хочу получить исходные данные из getInputLine, чтобы делать другие вещи.
Спасибо
1 ответ
Все заявления в do
блок должен иметь одинаковый тип (ну, должен иметь одинаковую монаду в своем типе). В вашем случае это InputT IO something
(с монадой InputT IO
).
getInputLine "$ "
имеет тип InputT IO (Maybe String)
, так что эта часть в порядке.
Тогда у вас есть case
выражение, что означает, что все ветви должны иметь одинаковый тип. Первая ветка просто return ()
, который получает тип InputT IO ()
, Пока все хорошо.
Вторая ветвь process $ words input
, Но это имеет тип IO ()
не InputT IO ()
Это то, что ожидает компилятор в этой точке.
Чтобы это исправить: к счастью, есть простой способ преобразовать ("поднять") значение типа IO x
в InputT IO x
, какой liftIO
функция:
Just input -> liftIO (process $ words input)
То есть, liftIO :: IO a -> InputT IO a
(на самом деле это более общее, чем это: liftIO :: (MonadIO m) => IO a -> m a
но это не имеет значения здесь).