Aron Lee
Aron Lee

Reputation: 617

Use where outside the Haskell function

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

Answers (1)

chepner
chepner

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:

  1. do { x <- y; foo x; } becomes y >>= (\x -> foo x).
  2. do { foo; bar; } becomes foo >> bar.
  3. do { let x = y; foo; } becomes let x = y in do foo
  4. 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

Related Questions