Definition on Haskell Where Function. Haskell where is not a function rather it is a keyword that is used to divide the more complex logic or calculation into smaller parts, which makes the logic or calculation easy to understand and handle.
In Haskell let, binding is used to bind the variables, which are very local. In Haskell, we can define any type of variable using let keyword before the variable name in Haskell. But their scope is local, we also have let in Haskell which is another form of defining the variable and use them after it.
Overview. Haskell guards are used to test the properties of an expression; it might look like an if-else statement from a beginner's view, but they function very differently. Haskell guards can be simpler and easier to read than pattern matching .
1: The problem in the example
f :: State s a
f = State $ \x -> y
where y = ... x ...
is the parameter x
. Things in the where
clause can refer only to the parameters of the function f
(there are none) and things in outer scopes.
2: To use a where
in the first example, you can introduce a second named function
that takes the x
as a parameter, like this:
f = State f'
f' x = y
where y = ... x ...
or like this:
f = State f'
where
f' x = y
where y = ... x ...
3: Here is a complete example without the ...
's:
module StateExample where
data State a s = State (s -> (a, s))
f1 :: State Int (Int, Int)
f1 = State $ \state@(a, b) ->
let
hypot = a^2 + b^2
result = (hypot, state)
in result
f2 :: State Int (Int, Int)
f2 = State f
where
f state@(a, b) = result
where
hypot = a^2 + b^2
result = (hypot, state)
4: When to use let
or where
is a matter of taste. I use let
to emphasize a computation (by moving it to the front) and where
to emphasize the program flow (by moving the computation to the back).
While there is the technical difference with respect to guards that ephemient pointed out, there is also a conceptual difference in whether you want to put the main formula upfront with extra variables defined below (where
) or whether you want to define everything upfront and put the formula below (let
). Each style has a different emphasis and you see both used in math papers, textbooks, etc. Generally, variables that are sufficiently unintuitive that the formula doesn't make sense without them should be defined above; variables that are intuitive due to context or their names should be defined below. For example, in ephemient's hasVowel example, the meaning of vowels
is obvious and so it need not be defined above its usage (disregarding the fact that let
wouldn't work due to the guard).
Legal:
main = print (1 + (let i = 10 in 2 * i + 1))
Not legal:
main = print (1 + (2 * i + 1 where i = 10))
Legal:
hasVowel [] = False
hasVowel (x:xs)
| x `elem` vowels = True
| otherwise = False
where vowels = "AEIOUaeiou"
Not legal: (unlike ML)
let vowels = "AEIOUaeiou"
in hasVowel = ...
I found this example from LYHFGG helpful:
ghci> 4 * (let a = 9 in a + 1) + 2
42
let
is an expression so you can put a let
anywhere(!) where expressions can go.
In other words, in the example above it is not possible to use where
to simply replace let
(without perhaps using some more verbose case
expression combined with where
).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With