Haskell pre-monadic I/O

前端 未结 3 1799
情歌与酒
情歌与酒 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条回答
  •  萌比男神i
    2020-12-04 18:26

    I'd prefer an example that works with modern GHC.

    For GHC 8.6.5:

    import Control.Concurrent.Chan(newChan, getChanContents, writeChan) 
    import Control.Monad((<=<))
    
    type Dialogue = [Response] -> [Request]
    data Request  = Getq | Putq Char
    data Response = Getp Char | Putp
    
    runDialogue :: Dialogue -> IO ()
    runDialogue d =
      do ch <- newChan
         l <- getChanContents ch
         mapM_ (writeChan ch <=< respond) (d l)
    
    respond :: Request -> IO Response
    respond Getq     = fmap Getp getChar
    respond (Putq c) = putChar c >> return Putp
    

    where the type declarations are from page 14 of How to Declare an Imperative by Philip Wadler. Test programs are left as an exercise for curious readers :-)

    If anyone is wondering:

     -- from ghc-8.6.5/libraries/base/Control/Concurrent/Chan.hs, lines 132-139
    getChanContents :: Chan a -> IO [a]
    getChanContents ch
      = unsafeInterleaveIO (do
            x  <- readChan ch
            xs <- getChanContents ch
            return (x:xs)
        )
    

    yes - unsafeInterleaveIO does make an appearance.

提交回复
热议问题