Equal (=) Vs left arrow (

To understand the real difference, you have to understand monads, and the desugaring described by @rightfold in their answer.

For the specific case of the IO monad, as in your getArgs example, a rough but useful intuition can be made as follows:

  • x <- action runs the IO action, gets its result, and binds it to x
  • let x = action defines x to be equivalent to action, but does not run anything. Later on, you can use y <- x meaning y <- action.

Programmers coming from imperative languages which allow closures, may draw this rough parallel comparison with JavaScript:

var action = function() { print(3); return 5; }

// roughly equivalent to x <- action
print('test 1')
var x = action()  // output:3
// x is 5

// roughly equivalent to let y = action
print('test 2')
var y = action    // output: nothing
// y is a function

// roughly equivalent to z <- y
print('test 3')
var z = y()       // output:3
// z is 5

Again: this comparison focuses on IO, only. For other monads, you need to check what >>= actually is, and think about the desugaring of do.

Leave a Comment