| > 1. a description of how to carry out I/O that is performed by a separate system > 2. does the I/O inside the function before returning How do you distinguish those two things? To put my cards on the table, I believe Haskell does 2, and I think my Haskell effect system Bluefin makes this abundantly clear. (Zig's `Io` seems to correspond to Bluefin's `IOE`.) There is a persistent myth in the Haskell world (and beyond) that Haskell does 1. In fact I think it's hard to make it a true meaningful statement, but I can probably just about concede it is with a lot of leeway on what it means for I/O to be "performed by a separate system", and even then only in a way that it's also true and meaningful for every other language with a run time system (which is basically all of them). The need to believe that Haskell does 1 comes from the insistence that Haskell be considered a "pure" language, and the inference that means it doesn't do I/O, and therefore the need that "something else" must do I/O. I just prefer not to call Haskell a "pure" language. Instead I call it "referentially transparent", and the problem vanishes. In Haskell program like main :: IO ()
main = do
foo
foo
foo :: IO ()
foo = putStrLn "Hello"
I would say that "I/O is done inside `foo` before returning". Simple. No mysteries or contradiction.https://hackage-content.haskell.org/package/bluefin/docs/Blu... |
It is not. The documentation and the type very clearly shows this:
https://hackage.haskell.org/package/base-4.21.0.0/docs/Prelu...
> A value of type `IO a` is a computation which, when performed, does some I/O before returning a value of type a.
So your function foo does no IO in itself. It returns a "computation" for main to perform. And only main can do this, since the runtime calls main. You can call foo as much as you like, but nothing will be printed until you bind any of the returned IO values.
Comparing it to other languages is a bit misleading since Haskell is lazy. putStrLn isn't even evaluated until the IO value is needed. So even "before returning" is wrong no matter how you choose to define "inside".