Haskell pre-monadic I/O

前端 未结 3 1800
情歌与酒
情歌与酒 2020-12-04 17:53

I wonder how I/O were done in Haskell in the days when IO monad was still not invented. Anyone knows an example.

Edit: Can I/O be done without the IO Monad in modern

3条回答
  •  再見小時候
    2020-12-04 18:26

    @sepp2k already clarified how this works, but i wanted to add a few words

    I'm really sorry for this. I don't think it is possible to write this function without unsafePerformIO

    Of course you can, you should almost never use unsafePerformIO http://chrisdone.com/posts/haskellers

    I'm using slightly different Request type constructor, so that it does not take channel version (stdin / stdout like in @sepp2k's code). Here is my solution for this:

    (Note: getFirstReq doesn't work on empty list, you would have to add a case for that, bu it should be trivial)

    data Request = Readline
                 | PutStrLn String
    
    data Response = Success
                  | Str String
    
    type Dialog = [Response] -> [Request]
    
    
    execRequest :: Request -> IO Response
    execRequest Readline = getLine >>= \s -> return (Str s)
    execRequest (PutStrLn s) = putStrLn s >> return Success
    
    
    dialogToIOMonad :: Dialog -> IO ()
    dialogToIOMonad dialog =
        let getFirstReq :: Dialog -> Request
            getFirstReq dialog = let (req:_) = dialog [] in req
    
            getTailReqs :: Dialog -> Response -> Dialog
            getTailReqs dialog resp =
                \resps -> let (_:reqs) = dialog (resp:resps) in reqs
        in do
            let req = getFirstReq dialog
            resp <- execRequest req
            dialogToIOMonad (getTailReqs dialog resp)
    

提交回复
热议问题