使用Haskeline的getInputLine输入

时间:2016-12-07 10:29:45

标签: haskell monads 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 个答案:

答案 0 :(得分:6)

do块中的所有语句必须具有相同的类型(嗯,其类型中必须具有相同的monad)。在您的情况下,这是InputT IO something(monad为InputT IO)。

getInputLine "$ "的类型为InputT IO (Maybe String),因此该部分正常。

然后你有一个case表达式,这意味着所有分支都需要具有相同的类型。第一个分支只是return (),其类型为InputT IO ()。到目前为止一切都很好。

第二个分支是process $ words input。但是它的类型为IO (),而不是InputT IO (),这是编译器在此时所期望的。

解决这个问题:幸运的是,有一种简单的方法可以将IO x类型的值转换为InputT IO x liftIO,即{{1}功能:

Just input -> liftIO (process $ words input)

liftIO :: IO a -> InputT IO a(实际上它比liftIO :: (MonadIO m) => IO a -> m a更通用,但这并不重要。)