I've been reading thinking functionally with Haskell to learn Haskell and I came across that. In the book it says that A where clause does not qualify an expression but the whole of the right hand side of a definition. I don't quite understand this means.
The book means that the following "expression" is not valid Haskell syntax:
x*x where x = 6
You can see it is invalid by either entering it at the GHCi prompt:
> x*x where x=6
<interactive>:11:5: error: parse error on input ‘where’
or using it in a program where an expression is expected:
mybrokenprogram = (x * x where x = 6) -- gives a parse error
Contrast this with:
let x=6 in x*x
which works from the GHCi prompt:
> let x=6 in x*x
36
and works fine as part of the other example:
myawesomeprogram = (let x = 6 in x*x)
The book is explaining that a where clause applies to the entire right hand side of its associated defintion:
myfinewhereclause = x*x+x
where x = 6*6
Here, the where clause provides a definition for x that applies to the whole right-hand side x*x+x. Even if there was some alternative definition of x in scope, the where clause would redefine x for the whole RHS:
my_argument_x_is_ignored x = x*x+x where x = 6*6
Here, the where clause provides a definition of x that applies to every usage of x in the expression x*x+x. It doesn't apply only to the last use of x, and you can't use parenthesis to make it apply only to the last use of x:
wontwork x = x*x + (x where x=6*6) -- won't work: bad syntax
It's nothing deep. It's just the way the where syntax works.
Related
I was learning some new Haskell today, when I tried something in ghci.
It basically boiled down to this:
Prelude> let x = 6
Prelude> x
6
Prelude> let y = show x
Prelude> y
"6"
Prelude> let x = show x
Prelude> x
"\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" --(repeats)
So can ghci not self-reference in assignment? I feel like it's akin to i = i++; in C, or trying to reference previous assignments of a let (not let*) in Scheme. Is there anyway to do this, or should I just use the easier let y = show x?
Definitions in Haskell are recursive by default. So the definition you made for x refers to the very same x, which is the reason for the very long string you are seeing, because x is defined to a String that is the result of calling show on itself, so you keep seeing the opening quotes for showing a string, and then those opening quotes escaped, and so on.
These kinds of definitions can be surprisingly useful. For example if you write:
let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
you can define the Fibonacci sequence in terms of itself as an infinite list.
Then you can do something like take 10 fibs to just see the first 10 elements.
It's self referencing indeed! It's trying to solve the equation
x = show x
Since show returns a string Haskell knows that x begins like "\"" and that's enough to guess the second character, which is enough for the third which is enough for the fourth...
And so on.
Yes, you can do a not-selfreferencing assignment in ghci, although it's a bit cumbersome:
let x = 5
x <- return $ show x
lets are recursive, while monadic bindings are not.
Again: yes, Haskell very much can self-reference in assignment, otherwise this would just give an error instead of printing something undecipherable, wouldn't it?
What you can not do in Haskell, ever, is modify / re-assign the value of a variable. It's just totally out of question: if you've once defined x as some value, x will keep this value forever. An assumption baked into the very language, and used to great avail by the compiler for lots of optimisations etc..
Now you wonder why you can write let x = ... again at all, didn't I just say this is not possible? The thing is, what you're doing there is define a new variable that also happens to have the name x, but that doesn't change anything about the old variable with the same name. You might expect this
Prelude> let x = 6
Prelude> let p = print x
Prelude> let x = 7
Prelude> p
to yield 7, but actually it prints 6 because p is still referring to the old variable x, not to the new one that was defined only later.
Still confused? Perhaps less strange is something like
n :: Int
n = 7
f :: IO ()
f = print $ replicate n "ha"
... -- much later, you've forgotten there was a global `n` up there...
g :: String -> String
g = take n
where n = 37
It's quite reasonable that f will take 37 characters, not 7, while any call to f continues to repeat the string only 7 times. After all, it's "g, where n has that value", but nothing else outside. Now, let is just where written the other way around. In particular, a do notation or your GHCi prompt is actually syntactic sugar for something like this:
let x = 6
in ( print x >> ( let y = show x
in ( print y >> ( let x = show x
in ( print x )
)
)
)
Each paren encloses a scope. Variables defined in outer scopes can be used, but local ones are preferred if found. So let x = show x in ( print x ) can be considered completely on its own, the original x = 6 is shadowed out of scope here. Therefore, the only way the definition can work is refer recursively to itself.
I tried following expression in prelude:
let x = x in x
and I've got following exception
Exception: <<loop>>
Why is the expression recursive?
let bindings in Haskell are (mutually) recursive, meaning that you can refer to any of the defined variables/functions (things to the left of the = signs) in any of their definitions (the stuff to the right of the = sign). For the case where you have arguments (functions), this is pretty much always the intuitive expected behaviour.
let fact n = if n == 0 then 1 else n * fact (n - 1) in fact 5
In the above, you probably are not surprised that fact (n - 1) can be used in the definition of fact n. In your example, you are using x in its own definition.
When Haskell tries to evaluate let x = x in x, it keeps trying to expand x (into the RHS x) hence the loop.
Someone told me Haskell does not have variables but bindings. Now what ever that means, I always wondered what the difference is when writing these bindings, like so:
x = 5
and
let x = 5
What is the difference here?
And a followup question: Am I even creating variables by doing this? If x is not a variable, what is it?
The only real difference is where they occur.
-- At top (file) level or in "where" blocks, omit "let".
x = 5
f1 y = x + y
where
x = 5
-- Inside expressions or do-blocks, "let" is required.
f2 y = let x = 5
in x + y
f3 y = do someAction
let x = 5
return (x + y)
In all cases, x is a variable. However, you cannot change (mutate) the value of the variable.
In the GHCi prompt, it seems like you change the value of a variable, but you cannot. You can only create new variables with the same name, the old variables still exist.
Prelude> let x = 3
Prelude> let f y = x + y
Prelude> let x = 10
Prelude> f 1
4
If you had really changed the value of x, then f 1 would be 11.
Haskell has variables, but we say they are bound rather than assigned. These are extremely similar notions, but they differ in whether they support multiple assignment - Haskell does not.
do let x = 1
let x = 2
print x -- prints "2"
When we say it does not, what we mean is that all variables are bound statically. This means that any time there's a reference to a variable, you can look back up through the code and find the one binding that it refers to.
Take, for example, Python, which does have multiple assignment.
def f(a):
x = 1 # first assignment
x = 2 # second assignment
for i in a:
x = i # third assignment
print x
print x
In the above example, there are three places where x is assigned. When we refer to x on the last line, we could be getting the 2 from the second assignment, or we could be getting one of the values from a from the assignment in the loop. Whether the third assignment took place depends on whether a was empty or not.
So let's look at similar code in Haskell:
f a = do let x = 1 -- first binding
let x = 2 -- second binding
for_ a $ \i -> do let x = i -- third binding
print x
print x
The final line of this output will always be "2", because at that point in the code, the second binding is the innermost binding that x received in that scope. If we were to introduce another closer binding, then we could change that:
f a = do let x = 1 -- first binding
let x = 2 -- second binding
for_ a $ \i -> do let x = i -- third binding
print x
let x = head a -- fourth binding
print x
But what we can never do is introduce ambiguity about which binding something refers to.
Here's the code.
largestDivisible :: (Integral a) => a
largestDivisible = head (filter p [100000,99999..])
where p x = x `mod` 3829 == 0
I am little bit confused. What is p in this case? Also, I do not understand the where expression in this particular example, because we got two expressions with p and x on the left side and we have one alignment, which is actually a boolean.
I would appreciate, if someone could explain me the above code.
p is a function, which accepts an argument x and returns True only if x is divisible by 3829. You can use where to define local functions just like you define local "values", using the same f x = y syntax you use to define top-level functions.
I was learning some new Haskell today, when I tried something in ghci.
It basically boiled down to this:
Prelude> let x = 6
Prelude> x
6
Prelude> let y = show x
Prelude> y
"6"
Prelude> let x = show x
Prelude> x
"\"\\\"\\\\\\\"\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\" --(repeats)
So can ghci not self-reference in assignment? I feel like it's akin to i = i++; in C, or trying to reference previous assignments of a let (not let*) in Scheme. Is there anyway to do this, or should I just use the easier let y = show x?
Definitions in Haskell are recursive by default. So the definition you made for x refers to the very same x, which is the reason for the very long string you are seeing, because x is defined to a String that is the result of calling show on itself, so you keep seeing the opening quotes for showing a string, and then those opening quotes escaped, and so on.
These kinds of definitions can be surprisingly useful. For example if you write:
let fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
you can define the Fibonacci sequence in terms of itself as an infinite list.
Then you can do something like take 10 fibs to just see the first 10 elements.
It's self referencing indeed! It's trying to solve the equation
x = show x
Since show returns a string Haskell knows that x begins like "\"" and that's enough to guess the second character, which is enough for the third which is enough for the fourth...
And so on.
Yes, you can do a not-selfreferencing assignment in ghci, although it's a bit cumbersome:
let x = 5
x <- return $ show x
lets are recursive, while monadic bindings are not.
Again: yes, Haskell very much can self-reference in assignment, otherwise this would just give an error instead of printing something undecipherable, wouldn't it?
What you can not do in Haskell, ever, is modify / re-assign the value of a variable. It's just totally out of question: if you've once defined x as some value, x will keep this value forever. An assumption baked into the very language, and used to great avail by the compiler for lots of optimisations etc..
Now you wonder why you can write let x = ... again at all, didn't I just say this is not possible? The thing is, what you're doing there is define a new variable that also happens to have the name x, but that doesn't change anything about the old variable with the same name. You might expect this
Prelude> let x = 6
Prelude> let p = print x
Prelude> let x = 7
Prelude> p
to yield 7, but actually it prints 6 because p is still referring to the old variable x, not to the new one that was defined only later.
Still confused? Perhaps less strange is something like
n :: Int
n = 7
f :: IO ()
f = print $ replicate n "ha"
... -- much later, you've forgotten there was a global `n` up there...
g :: String -> String
g = take n
where n = 37
It's quite reasonable that f will take 37 characters, not 7, while any call to f continues to repeat the string only 7 times. After all, it's "g, where n has that value", but nothing else outside. Now, let is just where written the other way around. In particular, a do notation or your GHCi prompt is actually syntactic sugar for something like this:
let x = 6
in ( print x >> ( let y = show x
in ( print y >> ( let x = show x
in ( print x )
)
)
)
Each paren encloses a scope. Variables defined in outer scopes can be used, but local ones are preferred if found. So let x = show x in ( print x ) can be considered completely on its own, the original x = 6 is shadowed out of scope here. Therefore, the only way the definition can work is refer recursively to itself.