jazzer97
jazzer97

Reputation: 157

Where clause in Haskell

I'm confused about how the where clause in Haskell works in a certain situation.

My biggest question is, is it possible to declare a variable that does something in the where clause and use back that declared variable through another variable declared in the where clause?

For example:

someFunc :: somefunc
.
| (guard expression)
| (guard expression)
where a = 1+3
      b = a + 2 --using back 'a' variable which was also declared in the where clause.

Is this possible? When i do this haskell does not report any error but I was having doubts if it's a correct.

Upvotes: 2

Views: 7407

Answers (3)

Yilmaz
Yilmaz

Reputation: 49182

calcProfit revenue cost= if revenue - cost >0
                         then revenue - cost
                         else 0

In this example we are repeating (revenuw-cost) your computation. This is a cheap operation but if it was an expensive operation you would be wasting resources. To prevent this, we use where clause:

calcProfit revenue cost = if profit >0 
                          then profit
                          else 0
           where profit= revenue-cost

With "where" clause we reverse the normal order used to write variables. In most of the programming languages, variables are declared before they’re used. In Haskell, because of referential transparency, variable order isn’t an issue.

As you see, we declare the variable "profit" in where clause and then we used it

Upvotes: 1

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476503

Yes, it is even possible to use the same variable in the expression as the one you define.

would work as well. In essence, the variables are just references to "expressions". So for your case you construct something that looks like:

    ┏━━━━━━━┓
b──>┃  (+)  ┃
    ┣━━━┳━━━┫   ┏━━━┓
    ┃ o ┃ o─╂──>┃ 2 ┃
    ┗━┿━┻━━━┛   ┗━━━┛
      │
      v
    ┏━━━━━━━┓
a──>┃  (+)  ┃
    ┣━━━┳━━━┫   ┏━━━┓
    ┃ o ┃ o─╂──>┃ 3 ┃
    ┗━┿━┻━━━┛   ┗━━━┛
      │
      │         ┏━━━┓
      ╰────────>┃ 1 ┃
                ┗━━━┛

This expression tree thus contains functions which point to other expression trees. Haskell will by default not evaluate these expressions: the expressions are evaluated lazily: only when you have to calculate these, you will calculate the corresponding value. Furthermore, if you are for example interested in the value of b, you thus will calculate the value of a, and thus the 1+3 expression will only be evaluated once. The same holds in the opposite direction: in case you first evaluate a, then evaluating b will benefit from the fact that a was already calculated. You can for example define two variables in terms of each other, like:

foo :: Int
foo = a
    where a = 1 + b
          b = 1 + a

but this will get stuck in an infinite loop since you will create an expression that looks like 1 + (1 + (1 + (...))).

We can even define a variable in terms of itself. For example the function below generates an infinite list of ones:

ones :: [Int]
ones = lst
    where lst = 1 : lst

This will be represented as:

      ┏━━━━━━━┓
lst──>┃  (:)  ┃<─╮
      ┣━━━┳━━━┫  │
      ┃ o ┃ o─╂──╯
      ┗━┿━┻━━━┛
        │
        v
      ┏━━━┓
      ┃ 1 ┃
      ┗━━━┛

Upvotes: 7

Chai T. Rex
Chai T. Rex

Reputation: 3020

Yes. The variables in the where clause can see other variables in the same where clause.

For doubts, you can test it out with a simpler structure to see if it gives the correct value:

testing = b
  where
    a = 1000
    b = a + 234

main = print testing

Does it print out 1234 as expected?

Upvotes: 8

Related Questions