Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Type of IO () in `let` Expression

Tags:

haskell

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’
like image 814
Kevin Meredith Avatar asked May 27 '16 03:05

Kevin Meredith


People also ask

What is the type of IO Haskell?

The IO type is abstract: no constructors are visible to the user. IO is an instance of the Monad and Functor classes.

What does the type IO String signify?

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 ().

What is an IO action Haskell?

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.

How is IO pure in Haskell?

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 .


2 Answers

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.

like image 77
Vaibhav Sagar Avatar answered Sep 23 '22 23:09

Vaibhav Sagar


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.

like image 34
chi Avatar answered Sep 23 '22 23:09

chi