Given:
λ: let f = putStrLn "foo" in 42
42
What is f
's type? Why does "foo"
not get printed before showing the result of 42
?
Lastly, why doesn't the following work?
λ: :t f
<interactive>:1:1: Not in scope: ‘f’
The IO type is abstract: no constructors are visible to the user. IO is an instance of the Monad and Functor classes.
putStrLn is a function that takes a single argument of type String and produces a value of type IO (). The IO () signifies an executable action that returns a value of type ().
IO actions are used to affect the world outside of the program. Actions take no arguments but have a result value. Actions are inert until run. Only one IO action in a Haskell program is run ( main ). Do-blocks combine multiple actions together into a single action.
Calculations involving such operations cannot be independent - they could mutate arbitrary data of another computation. The point is - Haskell is always pure, IO doesn't change this. So, our impure, non-independent codes have to get a common dependency - we have to pass a RealWorld .
What is
f
's type?
As you have correctly identified, it is IO ()
which can be thought of as an IO action that returns nothing useful (()
)
Why does "foo" not get printed before showing the result of
42
?
Haskell is lazily evaluated, but even seq
is not enough in this case. An IO action will only be performed in the REPL if the expression returns the IO action. An IO action will only be performed in a program if it's returned by main
. However, there are ways to get around this limitation.
Lastly, why doesn't the following work?
Haskell's let
names a value within the scope of an expression, so after the expression has been evaluated f
goes out of scope.
let f = ...
simply defines f
, and does not "run" anything. It is vaguely similar to a definition of a new function in imperative programming.
Your full code let f = putStrLn "foo" in 42
could be loosely translated to
{
function f() {
print("foo");
}
return 42;
}
You wouldn't expect the above to print anything, right?
By comparison, let f = putStrLn "foo" in do f; f; return 42
is similar to
{
function f() {
print("foo");
}
f();
f();
return 42;
}
The correspondence is not perfect, but hopefully you get the idea.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With