2016-06-20 14 views
0

Ich möchte eine Eingabezeichenfolge mit einer benutzerdefinierten Eingabeaufforderung lesen, jedoch stammt die Eingabeaufforderungszeichenfolge aus unreinem Kontext, daher kann ich readInputLine nicht verwenden, wie es ist. Ich habe versucht, eine Funktion auf this answerreadInputLine mit IO-String

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

aber ich bekomme

einen Fehler
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 } 

Update-Basis zu implementieren: es wurde basierend arbeiten auf @ bheklilr der answer

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

Sie wahrscheinlich nur verwenden müssen, um '' lift' Ihre IO String' in einen 'InputT IO String' d' s Lee

Antwort

3

Der Code

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

Ruft die entzuckert in

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

Wo

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

Diese Art Unterschrift bedeutet, dass m überall die gleiche Monad Instanz sein muss. Sie haben es ios :: IO String und \s -> getInputLine s :: String -> InputT n (Maybe String) gegeben, aber m kann nicht sowohl IO als auch InputT n sein, daher der Compilerfehler.

Sie können einfach liftIO auf ios verwenden, sofern instance MonadIO m => MonadIO (InputT m) definiert ist, was es ist. So können Sie einfach tun

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

Danke, verwenden Sie 'm' für' MonadException' und 'MonadIO'? – dimid

+1

@dimid 'liftIO' erfordert, dass die' Monad', in der Sie sich befinden, auch 'MonadIO' implementiert. Nach dem Betrachten der [Dokumentation] (https://hackage.haskell.org/package/haskeline-0.7.2.3/docs/System-Console-Haskeline-MonadException.html) scheint es, dass 'MonadException' bereits' MonadIO' erfordert, So können Sie diese Anforderung fallen lassen. Wenn Sie jedoch in einer anderen "Monade" arbeiten, ist es möglich, mehrere Einschränkungen für Ihr spezielles 'm' zu haben. Es ist nicht unüblich, 'mtl'-basierten Code mit Einschränkungen wie' (MonadState s m, MonadWriter w m, MonadIO m) => ... 'zu sehen – bheklilr