0

我想读取带有自定义提示的输入字符串,但是提示字符串来自不纯的上下文,因此我不能readInputLine按原样使用。我试图根据这个答案实现一个功能

getLineIO :: MonadException m => IO String -> InputT m (Maybe String)
getLineIO ios = do
    s <- ios
    res <- getInputLine s
    lift res

但我得到一个错误

   Couldn't match expected type ‘InputT m String’
                with actual type ‘IO String’
    Relevant bindings include
      getLineIO :: IO String -> InputT m (Maybe String)
        (bound at Main.hs:38:1)
    In a stmt of a 'do' block: s <- ios
    In the expression:
      do { s <- ios;
           return $ getInputLine s }

更新:根据@bheklilr 的回答让它工作

getLineIO :: (MonadException m, MonadIO m) => IO String -> InputT m (Maybe String)
getLineIO ios = do
      s <- liftIO ios
      getInputLine s
4

1 回答 1

3

编码

do
    s <- ios
    res <- getInputLine s
    lift res

脱糖成

ios >>= \s -> (getInputLine s >>= \res -> lift res)

在哪里

(>>=) :: Monad m => m a -> (a -> m b) -> m b

这种类型签名意味着它m必须始终是相同的Monad实例。您已经给出了ios :: IO Stringand \s -> getInputLine s :: String -> InputT n (Maybe String),但m不能同时是IOand InputT n,因此编译器错误。

您可以只使用liftIO提供iosinstance MonadIO m => MonadIO (InputT m)已定义,就是这样。所以你可以做

getLineIO :: (MonadException m) => IO String -> InputT m (Maybe String)
getLineIO ios = do
    s <- liftIO ios
    res <- getInputLine s
    lift res
于 2016-06-20T15:25:39.937 回答