| From my understanding, this is not Haskells IO - though my time with Haskell is limited. 1. Haskell uses special notation 'do' to handle access to IO wrapped values, e.g. (contrieved example, one would not use do for such simple cases) y = do x <- xWithIO
return x + 1
instead of y = x + 1
2. Haskell method signatures do include IO, e.g. doSomething :: Int -> IO Int
instead of def doSomething(i:Int):Int
3. Because IO is usually not the only effect managaging monad, as I've said in another comment, the type signature usually uses a type alias that does alias a monad transformer stack like type Result a = ReaderT Env ( ErrorT String ( StateT Integer Identity))
or concurrency mixed in4. This the same as my Scala code, where I have cats FutureT monad transformers with Scalactic errors OrT Every stacks showing up all over my APIs as a type alias of 'WithErrors'. 5. 'Also, parallelism is "free" on pure code.' Not sure what's that got to do with it, but yes if you have no concurrency problems (concurrent writes to shared data) you don't need to think about concurrency and parallelism is free. But if my understanding is wrong, I'm happy to learn something about concurrency in Haskell without it showing in code and type signatures. |
IO code always returns a promise, and the next statement on a `do` block may await the previous promise and yield the execution to whatever other piece of code can run, based on some rules on the compiler, based in large part on data dependency. If I'm reading your comment correctly, that is what you are asking for.