Reputation: 157
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
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
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
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