Truly insane.
Truly insane.
Now do it inside a vanilla function that isn't implicitly run inside the IO monad.
What do you mean by run implicitly? I explicitly put IO expressions in the main function and they run. That’s the same as any imperative language.
I’m trying to figure out what you’re getting at. Are you saying it’s hard to do IO outside of the IO Monad?
> Look at all the monad insanity Haskell has to do to get the equivalent of a print statement
but it's easy to do that! If you meant something more complex and subtle perhaps you should have made a more complex and subtle claim.
> There is nothing that has to do with monads at all in printing a string. The idea that `putStrLn "hello world"` is monadic is as absurd as saying that `[1,2,3]` is monadic.
You haven't linked any exemplar tutorials, but I feel confident in saying the ones you're referring to teach the general concept of monads, and not how to do IO with monads.
Quite a number of JavaScript developers learned how to use `andThen` with Promises/A+ back in the day, and they didn't need to learn about monads either. (In fact, when it was raised that promises are really monads, there was serious drama and outrage [1] -- an existence proof if there ever was one, that you can use something productively without understanding it as a monad.)
Likewise, nobody would claim that you need to understand monoids before you can concatenate lists. Concatenating lists is as native to lists as sequencing commands is to IO; it's just part of how those types work. The monad interface abstracts over that idea, and learning that abstraction in its full generality is, typically, what people stumble on.
[0]: https://blog.jle.im/entry/io-monad-considered-harmful.html
[1]: https://github.com/promises-aplus/promises-spec/issues/94
Relative to programming in general, monads are easy to work with, easy enough to understand, but I’ll grant you often poorly explained.
Those people writing monad tutorials (those are written about as often as they are read) aren't trying to learn how to do I/O.
(And of course "it's just a monoid in the category of endofunctors".)
myMethod :: IO ()
myMethod = putStrLn "Hello World!"
Yes, so hard... "insane" /s f x y z = do
let
foo = x + y
bar = foo * z
putStrLn $ "Here's bar" <> (show bar)
pure bar
If all you want is to log to the console for debugging from pure code, it would look like f x y z =
let
foo = x + y
bar = foo * z
in
trace ("Here's bar" <> (show bar)) bar
Not recommended, but if you're dead set on commingling your effectful and pure code, you can freely mix them with the function unsafePerformIO.In my experience having to write large applications with significant test coverage, the time savings from not screwing around with stubs and mocks and dealing with the external effects of test runs -- the relative annoyance of using a couple "do"s and "pure"s and separating out data transformation from IO is a small price to pay.
> Look at all the monad insanity Haskell has to do to get the equivalent of a print statement
perhaps you really meant
> Look at all the monad insanity Haskell has to do to get the equivalent of a print statement within pure code
I still don't agree as such, but yes, there is indeed ceremony involved in turning something that was pure into something effectful. That is in fact the whole point!
main = putStrLn “foo” >> putStrLn “bar”