GHCi "let" -- what does it do?
While programming in GHCi, you're like programming in the IO monad with do
syntax, so for example you can directly execute an IO
action, or use monadic bind syntax like r <- someIOFun
.
let
is also a part of do
so you can also use this. I think it's being desugared into let .. in <rest of the computation>
, so for example when you do this:
ghci> let a = 1
ghci> someFun
ghci> someFun2
It's like:
let a = 1 in
do someFun
someFun2
Here's the relevant part of the documentation.
GHCI statements are executed as IO computation. So let
is same as what you have inside an IO
monad where you bind non-IO expression using let
.
For more down-to-the-code details, this comment in TcRnDriver.lhs might be enlighting:
--------------------------------------------------------------------------
Typechecking Stmts in GHCi
Here is the grand plan, implemented in tcUserStmt
What you type The IO [HValue] that hscStmt returns
------------- ------------------------------------
let pat = expr ==> let pat = expr in return [coerce HVal x, coerce HVal y, ...]
bindings: [x,y,...]
pat <- expr ==> expr >>= \ pat -> return [coerce HVal x, coerce HVal y, ...]
bindings: [x,y,...]
expr (of IO type) ==> expr >>= \ it -> return [coerce HVal it]
[NB: result not printed] bindings: [it]
expr (of non-IO type, ==> let it = expr in print it >> return [coerce HVal it]
result showable) bindings: [it]
expr (of non-IO type,
result not showable) ==> error
So a command at the GHCi prompt can have up to three effects: Some code is evaluated, some things are printed, and some variable names are bound. Your case (the first one in the comment) binds variables, but does not print.
The syntax does resemble the do-notation, so @sinan’s answer is somewhat right, but it is not really what is happening under the hood – otherwise, for example, nothing would ever be printed.