Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

The IO type can be constructed in all kinds of ways. For instance, using `putStrLn` is probably the most common

    putStrLn "hello world" :: IO ()
As IO is an instance of Functor we can use that interface, for instance

    fmap (const 1) (putStrLn "hello world") :: IO Int
That would be using IO's functorial interface. As an extension to a functorial interface we also have a monadic interface. This affords us a "most boring" way of creating new IO values

    -- very different from putStrLn
    -- it doesn't actually represent *doing* anything at all
    return "hello world" :: IO String
and also, finally, a way at getting at values "inside" of IO and therefore "compose" values of IO

    -- getLine :: IO String

    capitalizer :: IO ()
    capitalizer = getLine >>= (\line -> putStrLn (map toUpper line))
So, the emphasis is that IO is "just" another type. One shouldn't refer to "the IO monad" as anything privileged unless you're actively referring to using (return, >>=) with IO. Generally "the IO monad" explains very little of IO's power as "being a monad" is a very small part of any type's interface.

---

To be clear, here are some other interfaces we can use from IO (besides just other IO value constructors)

* combining IO with exception handlers with

    catch :: IO a -> (e -> IO a) -> IO a
* forking new threads with

    forkIO :: IO () -> IO ThreadId
* embedding IO into another type with

    -- extremely common
    liftIO :: MonadIO m => IO a -> m a
* converting an IO action into an asynchronous action with

    async :: IO a -> IO (Async a)
* assigning a IO action pointed at by a finalizer to a memory pointer with

    newForeignPtr :: FunPtr (Ptr a -> IO ()) -> Ptr a -> IO (ForeignPtr a)


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: