Reputation: 617
I'm wondering whether we can use where outside a function? e.g.
fun::Int->Int
fun n = n + 1
main = do
fun x where x = 30
Obviously it does't work when I compile it,
I want to declare x as local variable for fun only
Upvotes: 0
Views: 342
Reputation: 530843
Your function has the wrong type to be used as the final expression in a do
block. It needs to return an Monad m => m Int
value, not simply an Int
. As main
(in its usual use) is required to be an IO
action, this means m
should be IO
.
fun :: Int -> IO Int
fun n = return (n + 1)
A let
would be more appropriate than a where
in this case, though.
main = do
let x = 30 in fun x
Now, x
is in scope only for the call to fun
. If you wrote
main = do
let x = 30
fun x
then x
is technically in scope for the rest of the do
block, not just the call to fun
. Despite sharing the same keyword let
, there is a distinct difference between a let
in a do
block and a regular let
expression. (The relationship is that
do
let name = value
foo
is equivalent to
let name = value
in do
foo
)
Note that do
itself does not create a monadic value; it is simply syntactic sugar for various operators which assume monadic properties. A quick overview:
do { x <- y; foo x; }
becomes y >>= (\x -> foo x)
.do { foo; bar; }
becomes foo >> bar
.do { let x = y; foo; }
becomes let x = y in do foo
do foo
becomes foo
.Most relevant to your code is rule 4; a single expression in a do
block is equivalent to the expression by itself, meaning you can strip the do
. Only after the do
block is desugared does Haskell begin to type-check the result.
Upvotes: 4