Используйте входные данные из 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 но это не имеет значения здесь).

Другие вопросы по тегам