2015-01-20 9 views
6

Angesichts der Proof of Concept-Code unten möchte ich in der Lage sein, meine foo Funktion mit der Fähigkeit, die Zeichenfolge Paul! und die Möglichkeit, auszugeben der Rückgabewert innerhalb des InputT Monade-Transformators ohne Verwendung von unsafePerformIO, um den IO-Wrapper nach runExceptT zu entfernen.Führen Sie einfache IO in Haskeline, innerhalb von InputT Monad, ohne auf unsafePerformIO

import Control.Monad.Except 

import System.IO.Unsafe (unsafePerformIO) 
import System.Console.Haskeline 


type ErrorWithIO = ExceptT String IO 


foo :: String -> ErrorWithIO String 
foo "paul" = do liftIO $ putStrLn "Paul!" 
       return "OK!" 
foo _ = throwError "ERROR!" 


runRepl :: IO() 
runRepl = runInputT defaultSettings $ loop 


loop :: InputT IO() 
loop = do 
    line <- getInputLine "> " 
    case line of 
     Nothing -> return() 
     Just input -> do return $ putStrLn "asd" 
         case unsafePerformIO $ runExceptT $ foo input of 
          Left err -> outputStrLn err >> loop 
          Right res -> do 
           x <- outputStrLn . show $ res 
           loop 




main :: IO() 
main = runRepl >> putStrLn "Goodbye!" 

Fehle ich etwas offensichtlich hier?

Antwort

10

Seit InputT IO ist ein MonadIO, Sie liftIO mit dieser Art verwenden können:

liftIO :: IO a -> InputT IO a 

So

do ... 
    x <- liftIO $ runExceptT $ foo input 
    case x of 
    Left err -> ... 
    Right res -> ... 

Alternativ kann statt Control.Monad.Trans.lift verwenden.

+0

Ich habe diese Lösung bereits ausprobiert, bekomme aber einen Kompilierfehler: 'Keine Instanz für (MonadIO (InputT IO)) durch Verwendung von 'liftIO'' – Paul

+0

Gleiches für die einfache' lift' Lösung: 'No Beispiel für (MonadTrans InputT) aus einer Verwendung von "Lift" – Paul

+0

@Paul Surprising ... hier habe ich so ein Beispiel. Vielleicht müssen Sie Control.Monad.IO.Class' importieren? – chi

Verwandte Themen