Hence the semantics are the same - just without any compiler feature like async/await.
Hence the semantics are the same - just without any compiler feature like async/await.
For example, if you have, say,
`getIntFromSomewhere :: IO Int`
and you want to apply a pure function of type `Int -> Int` to it. Supppose the pure function adds one. You might initially think that that's all there is to it, you don't want IO involved in what happens next. But of course, the only reason you would ever do some pure computation is to use the result to have some effect on the world, eg printing it to a console. So actually in a sense, you do want to stay in IO.
myIOAction :: IO ()
myIOAction = do
myInt <- getIntFromSomewhere
print (addOne myInt)
As you say, you can't pull the int out of getIntFromSomewhere without operating in an IO action. But why would we want to, since we obviously want to make use of that value to affect the outside world? And of course, that doesn't mean we have any issues getting that int into a pure function `addOne :: Int -> Int` first, before eventually (immediately, in this case) making use of the result to perform some IO.IOW, Haskell does have coloring, and its coloring does manifest through the IO monad, but that does not mean that all monads have color. Sort of like how you can't do, "Socrates is a man, Socrates is dead, therefore all men are dead."
But in general you can't do that with monads, in particular not if you just have "any" monad at hand but you don't know which one it is. And IO is one example, parsers would be another one.
Monad is a typeclass (analogous to an interface in OOP or traits in Rust). IO is a type. To make some type a member of monad (or any other typeclass), you just need to write the required functions in an instance declaration.
You can make a type a member of as many typeclasses as you want. List is a member of Foldable, Monad, etc. Calling that a special isn’t quite right as it is very common for a type to be a member of many typeclasses.
You’re entirely correct in saying the Monad typeclass offers no way to extract values. But there actually is an extract function called unsafePerformIO with type “IO a -> a”. The name says it all: use it and you’ll lose all of the safety normally afforded by keeping data derived from effects inside the IO type.