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

"do" is just syntax. You could write the above as:

    connectSqlite3 "test1.db" >>= \ conn ->
        prepare conn "INSERT INTO test VALUES (?, ?)" >>= \ stmt -> 
          >> execute stmt [toSql 1, toSql "one"]
          >> execute stmt [toSql 2, toSql "two"]
          >> execute stmt [toSql 3, toSql "three"]
          >> execute stmt [toSql 4, SqlNull]
          >> commit conn
          >> disconnect conn
and it's "just" a bunch of nested lambdas with no "do" in sight. What's different from "regular" code is that those lambdas 1) return IO actions, and 2) are strung together with monadic bind (>>=) to build one big IO action.

To be sure, in this case the do version is much easier to read (that's why "do notation" exists). It can be used with any monad, though - nothing ties it particularly to IO.



Maybe I should have been clearer but the basic point is that monadic code has a different interface

    bar (foo x) --pure Haskell
vs

    foo x >>= bar --monadic Haskell
vs

    bar(foo(x)) -- in C you write both cases like this.


You're close, but it's not really so clear cut.

foo x ++ bar -- "pure" or "monadic"?

foo x >>= baz -- "pure" or "monadic"?

What if (foo x) is a list in both cases?

(>>=) is just an operator. The values that it operates on are anything with a Monad instance, just like the values that (+) operates on are anything with a Num instance. There is nothing voodoo about monads or about bind (>>=); such voodoo as there is lies solely in IO, which is interacted with the same way as other values (though certainly what you can do with (IO a) is more limited than what you can do with (Maybe a)).


I used to think that Monad was some alternative realm in Haskell, a realm where purity didn't exist and everything was written in an alternative, built-in language (do-notation). That's because people tend to refer to using Monads as "working in the X-Monad", as if it is some... place. But then it turned out... Oh, so it's basically just a signature/interface/type class.


True! But one neat thing is that, if you have a black-box abstract data type then you can force people to use the provided Monad interface if they want to do stuff with it. The IO monad does exactly this to create its "alternative realm"; there is no way to get "out" of IO once you get in , the only way to run an IO computation is to have it be directly or indirectly called by "main" and the only primitive way to compose IO computations is with the monadic combinators.


I don't know... I think both perspectives (monad as context vs. monad as data) are valid and useful.

That said, the additional cruft (purity doesn't exist, do notation is mandatory, &c) is well worth shedding.




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

Search: