Reputation: 4603
I'm trying to use the variable defined in the outer scope within an action defined in do
block using where
:
module Main where
main :: IO ()
main = do
outerVar <- return "a"
doSomething
where
doSomething :: IO String
doSomething = putStrLn ("outerVar: " ++ outerVar)
Given this snippet, I'm trying to understand why does the compiler return the following error:
error: Variable not in scope: outerVar :: [Char]
|
9 | doSomething = putStrLn ("outerVar: " ++ outerVar)
|
Based on my understanding - doSomething
function should create some kind of a "closure" to contain the value of outerVar
(which I've just found out is called a free variable), but that doesn't happen.
I've spent quite a lot of time trying to figure out why exactly does this error happen. I'm quite embarassed as, even for me as a Haskell newbie, it seems almost like a basic concept that should be obvious but it isn't - hopefully I'm wrong. I couldn't find any answers when searching for "where in do block scope", "where closure" or similar keywords. This page that compares let
and where
doesn't mention my case, the closest example I've found is the first bit of code from here where the "Lambda lifting" topic is covered. They're able to use n
variable from outer scope within the function defined in where
, but it's not in a do
block as my case is.
So my question is - why exactly is outerVar
variable not in scope of doSomething
?
Upvotes: 2
Views: 578
Reputation: 18249
do
blocks are just syntactic sugar for chaining monadic values using >>=
and lambda functions. Your block is first translated by the compiler into:
return "a" >>= \outerVar -> doSomething
where doSomething =...
It should be obvious now that outerVar
is not in scope outside the lambda to which it is an argument.
Upvotes: 4