IO Monad Considered Harmful
blog.jle.im
IO Monad Considered Harmful
1–10 of 75 posts
Re: IO Monad Considered Harmful
#2Re: IO Monad Considered Harmful
#3Re: IO Monad Considered Harmful
#4I wish the author had explained what the difference between using the IO type and using the IO type via the monadic interface looked like. As a Haskell beginner, this article just makes me more confused. Can someone share an example or clarify?
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)Re: IO Monad Considered Harmful
#5I wish the author had explained what the difference between using the IO type and using the IO type via the monadic interface looked like. As a Haskell beginner, this article just makes me more confused. Can someone share an example or clarify?
Here's a function that has type `IO ()` but doesn't obviously use `IO`'s monadic interface.
foo = print "hello"
`print` may use `IO`'s monadic interface under the hood, I don't know.Here's some code that has type `IO ()` and does use `IO`'s monadic interface.
foo = do
str
which is de-sugared to foo = getLine >>= \str -> print str
which you can, if you like concise code, feel free to shorten to foo = getLine >>= print
The important part is `>>=` (pronounced "bind"), which is defined in the monad typeclass. (A typeclass is like a Java interface, by the way.)Re: IO Monad Considered Harmful
#6I wish the author had explained what the difference between using the IO type and using the IO type via the monadic interface looked like. As a Haskell beginner, this article just makes me more confused. Can someone share an example or clarify?
Yes. Here's a function that has type `IO ()` but doesn't obviously use `IO`'s monadic interface. foo = print "hello" `print` may use `IO`'s monadic interface under the hood, I don't know. Here's some code that has type `IO ()` and does use `IO`'s monadic interface. foo = do str which is de-sugared to foo = getLine >>= \str -> print str which you can, if you like concise code, feel free to shorten to foo = getLine >>=…
foo = print =
which often reads better when trying to build something that looks more like a nested function call and less like a pipeline.Re: IO Monad Considered Harmful
#7I wish the author had explained what the difference between using the IO type and using the IO type via the monadic interface looked like. As a Haskell beginner, this article just makes me more confused. Can someone share an example or clarify?
I think his point is that the IO type may be an example of a monad, but shut up about the monad part because it's not relevant to learning how to use it.
Re: IO Monad Considered Harmful
#8I wish the author had explained what the difference between using the IO type and using the IO type via the monadic interface looked like. As a Haskell beginner, this article just makes me more confused. Can someone share an example or clarify?
import Data.Char
main = (fmap.fmap) toUpper getLine
monadic (but still doesn't utilize extra power granted by monadic interface, since it produces the same result as above): import Data.Char
main = do
x Re: IO Monad Considered Harmful
#9OK, so you know Java interfaces? Haskell has something just like that. They're called "type classes", though. But it works pretty much the same way. When you write out a class definition, you write A) the name of the class B) all the functions the class has to support and C) the types of those functions. (Like a Java interface definition.)
Haskell has a type class called "Monad". To "implement the monad interface", in Java parlance, you have to implement two functions. The first is called "bind", but it's written ">>=". Here's its definition:
>>= :: m a -> (a -> m b) -> m b
Let's say our Monad was called `Foo`. In Java-land, this means the function takes a `Foo`, a function that takes an `a` and returns a `Foo`, and it uses those two things to return a `Foo`.The other function is "return", which is defined as
return :: a -> m a
Which, in Java terminology, means it takes an `a` and returns a `Foo`.If you implement those two functions, you now have a Monad.
If you've been told that Monads do anything in particular, you've been told wrong. Monads don't necessarily have anything to do with IO, or sequencing, or state, or anything like that.
It just so happens that those two functions (">>=" and "return") are super useful for representing a whole lot of common things, which happen to include things like IO and stateful algorithms. Monads don't have to do either of those things, but they certainly can.
Re: IO Monad Considered Harmful
#10I wish the author had explained what the difference between using the IO type and using the IO type via the monadic interface looked like. As a Haskell beginner, this article just makes me more confused. Can someone share an example or clarify?
The problem with learning about the monad typeclass first is that it is a very very high level abstraction, and abstractions are near impossible to understand without a working understanding of examples that they might abstract.