Using where in a list - haskell

Is there any way to use a where expression inside the list syntax? I imagined something like this would work:
foo = [i where i = 1]
But compilation yields:
error: parse error on input ‘where’
It's possible to use let ... in inside a list:
foo = [let i = 1 in i]
So I assume that where and let behave as different syntactic constructs?
I'm aware it's possible to do:
foo = [i] where i = 1
... but for more complicated lists the distance between the i and the i = 1 is too far for it to be clear - see the context section below and imagine many more test cases, and this testGroup itself nested inside a list.
Context
I ran across this while trying to write a readable testcase:
testGroup "toInput"
[
testProperty "toInput '*'" (forAll others conversionFails)
where others = arbitrary `suchThat` (\c -> c `notElem` exclChars)
conversionFails c = toInput c == Nothing
]
The equivalent with let just isn't as satisfying to read imo (and, more concretely, when surrounded by other test cases, the testProperty not being on the same indentation as them makes it harder to follow).
testGroup "toInput"
[
let others = arbitrary `suchThat` (\c -> c `notElem` exclChars)
conversionFails c = toInput c == Nothing
in
testProperty "toInput '*'" (forAll others conversionFails)
]

Like the Haskell Wiki article says:
It is important to know that let ... in ... is an expression, that is, it can be written wherever expressions are allowed. In contrast, where
is bound to a surrounding syntactic construct, like the pattern matching line of a function definition.
So in short, where is bound to the clause of a function declaration, whereas let is more locally scoped in an expression. If you write where, it is visible for the entire clause, like:
f a | a > 0 = g b b
| otherwise = b
where b = g a a
so here the where is visible for the two guards, a let is more locally scoped. If you write let y = f x in y * y, then that y is only visible in the in ... part. For example we can write:
Prelude> let a = 4 in (let a = 2 in a) + a
6
So here the inner a is 2 whereas the outer is 4. This might end up to be very confusing. If we would define variables with the same name in a where clause, this would result in name conflicts.
In case your code sample is a single function, you can of course move this out of the list definition, like:
foo exclChars =
testGroup "toInput" [testProperty "toInput '*'" (forAll others conversionFails)]
where others = arbitrary `suchThat` (`notElem` exclChars)
conversionFails = isNothing . toInput

[1 | 1==2] is a list comprehension too. 1==2 is a Boolean expression.
In your example foo = [let i = 1 in i], the let i = 1 in i is an expression as well.
Indeed where and let are different. let forms an expression, but where does not - it is a part of a definition (a = b where ...).
Difference is, a variable defined by where can be used in the definition's guards, whereas let goes on the right hand side of the = sign.
To your question, just move ] before the where, and it will become part of the definition where it appears.

You might be looking forward to using list comprehensions. In list comprehensions, you could use | which means such that, and you can say [ i | i <- [1] ]. So, you might use them as follows: [ ... | others <- [suchThat arbitrary (\c -> notElem c exclChars)] in your example.

I'm unsure about why do you want this specific list comprehension, but this works, and you can try it in GHCi:
> [ i | let i=1 ]
[1]
You can't instead use where in a list comprehension to this effect.

Related

What is a = a doing in haskell? [duplicate]

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.

Why `where` produces a parse error inside list comprehension, but `let` doesn't?

Let's define a simple function called func:
func :: [Int] -> [Int]
I would like to use a where clause inside a list comprehension when defining this bogus function.
func xs = [ y where y = x + 1 | x <- xs]
Unfortunately, while trying to compile I get the following message:
parse error on input `where'
If I decide to use the let clause, everything works just fine:
func xs = [ let y = x + 1 in x | x <- xs] -- compilation successful
Why can't I use where like I originally intended to?
As you can see in the Haskell Report (https://www.haskell.org/onlinereport/exps.html#list-comprehensions) list comprehensions take an expression in the left hand side. let is an expression, whereas where is part of top level declarations. Hence, it's not allowed there.
This is because List comprehensions are equivalent to do-syntax.
To be clear, this:
[f a b q | a <- as, b <- bs, let q = a + b]
Is equivalent to:
do a <- as
b <- bs
let q = a + b
return (f a b q)
And let expressions are permitted in do-blocks.
As for why where clauses aren't permitted, they're intended to provide a temporary scope in a top-level declaration.
Ie:
binding = la da fu gu
where la a b c = c a b
da = 6
...
In other words, where is only permitted after a variable has been described, and therefore is not correct in list comprehensions.

ghci self-referencing assignment

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.

Haskell: Where vs. Let

I am new to Haskell and I am very confused by Where vs. Let. They both seem to provide a similar purpose. I have read a few comparisons between Where vs. Let but I am having trouble discerning when to use each. Could someone please provide some context or perhaps a few examples that demonstrate when to use one over the other?
Where vs. Let
A where clause can only be defined at the level of a function definition. Usually, that is identical to the scope of let definition. The only difference is when guards are being used. The scope of the where clause extends over all guards. In contrast, the scope of a let expression is only the current function clause and guard, if any.
Haskell Cheat Sheet
The Haskell Wiki is very detailed and provides various cases but it uses hypothetical examples. I find its explanations too brief for a beginner.
Advantages of Let:
f :: State s a
f = State $ \x -> y
where y = ... x ...
Control.Monad.State
will not work, because where refers to
the pattern matching f =, where no x
is in scope. In contrast, if you had
started with let, then you wouldn't
have trouble.
Haskell Wiki on Advantages of Let
f :: State s a
f = State $ \x ->
let y = ... x ...
in y
Advantages of Where:
f x
| cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
where
a = w x
f x
= let a = w x
in case () of
_ | cond1 x = a
| cond2 x = g a
| otherwise = f (h x a)
Declaration vs. Expression
The Haskell wiki mentions that the Where clause is declarative while the Let expression is expressive. Aside from style how do they perform differently?
Declaration style | Expression-style
--------------------------------------+---------------------------------------------
where clause | let expression
arguments LHS: f x = x*x | Lambda abstraction: f = \x -> x*x
Pattern matching: f [] = 0 | case expression: f xs = case xs of [] -> 0
Guards: f [x] | x>0 = 'a' | if expression: f [x] = if x>0 then 'a' else ...
In the first example why is the Let in scope but Where is not?
Is it possible to apply Where to the first example?
Can some apply this to real examples where the variables represent actual expressions?
Is there a general rule of thumb to follow when to use each?
Update
For those that come by this thread later on I found the best explanation to be found here: "A Gentle Introduction to Haskell".
Let Expressions.
Haskell's let expressions are useful
whenever a nested set of bindings is
required. As a simple example,
consider:
let y = a*b
f x = (x+y)/y
in f c + f d
The set of bindings created by a let
expression is mutually recursive, and
pattern bindings are treated as lazy
patterns (i.e. they carry an implicit
~). The only kind of declarations
permitted are type signatures,
function bindings, and pattern
bindings.
Where Clauses.
Sometimes it is convenient to scope
bindings over several guarded
equations, which requires a where
clause:
f x y | y>z = ...
| y==z = ...
| y<z = ...
where z = x*x
Note that this cannot be done with a let expression, which only scopes over the expression which it encloses. A where clause is only allowed at the top level of a set of equations or case expression. The same properties and constraints on bindings in let expressions apply to those in where clauses. These two forms of nested scope seem very similar, but remember that a let expression is an expression, whereas a where clause is not -- it is part of the syntax of function declarations and case expressions.
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 = ...
Sadly, most of the answers here are too technical for a beginner.
LHYFGG has a relevant chapter on it -which you should read if you haven't already, but in essence:
where is just a syntactic construct (not a sugar) that are useful only at function definitions.
let ... in is an expression itself, thus you can use them wherever you can put an expression. Being an expression itself, it cannot be used for binding things for guards.
Lastly, you can use let in list comprehensions too:
calcBmis :: (RealFloat a) => [(a, a)] -> [a]
calcBmis xs = [bmi | (w, h) <- xs, let bmi = w / h ^ 2, bmi >= 25.0]
-- w: width
-- h: height
We include a let inside a list comprehension much like we would a predicate, only it doesn't filter the list, it only binds to names. The names defined in a let inside a list comprehension are visible to the output function (the part before the |) and all predicates and sections that come after of the binding. So we could make our function return only the BMIs of people >= 25:
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).

Use 'let' in 'if' expression

I need a function that works like this:
foo :: Integer -> Integer -> [Integer]
foo a b = do
let result = []
let Coord x y = boo a b
if x > 0
let result = result ++ [3]
if y > 0
let result = result ++ [5]
if x < a
let result = result ++ [7]
if y < b
let result = result ++ [9]
result
I can not use the guards because the result can have more then one element. But as I see I can not use 'let' in the 'if' expression:
all_possible_combinations.hs:41:14: parse error on input `let'
How can I check multiple expressions and add new elements in the list?
I search not only imperative solution, but the functional one.
Other people have said why what you tried doesn't work. Here is a concise way of doing what you want:
foo :: Integer -> Integer -> [Integer]
foo a b = map snd (filter fst [(x > 0, 3),
(y > 0, 5),
(x < a, 7),
(y < a, 9)])
where Coord x y = boo a b
So how does this work?
We start with a list of pairs. The second element of each pair is the value we might want to include in the return value from foo. The first element of each pair tells us whether we actually want to include it.
Then we call filter fst, which throws away all the pairs where the condition is false.
Finally, we call map snd, which throws away the conditions (all the ones that are left are true), and keeps the values we are interested in.
Three things:
You can use let inside an if expression, but it needs to be followed by in or inside a do block. Either way the expression which uses the name you just bound with let, needs to be in the same if. I.e. you can do:
if x > 0
then let a = 42 in a+x
else 23
but not
if x > 0
then let a = 42 in ()
else let a = 23 in ()
print a
You can not use let to change the value of an existing variable. As a matter of fact, you can not change the value of a variable, ever.
If you use the name bound on the LHS of = on the RHS of the = it will refer recursively to itself - not to any previous binding. In other words let x = x+1, causes infinite recursion, it does not increase the value of x by one.
To do what you want to, you'd need to restructure your code to something like this:
let result1 = if x > 0 then [3] else []
let result2 = if y > 0 then result1 ++ [5] else result1
let result3 = if x < a then result2 ++ [7] else result2
if y < b then result3 ++ [9] else result3
Note that it's usually a bad idea, performance wise, to use ++ to append at the end, instead of using : and then reverseing the list at the end.
EDIT: My thanks to sepp2k for pointing out what was intended. It was even more imperative than I could grok with my Haskell-colored glasses on...
Here's a quick-n-dirty solution:
result = (if x > 0 then [3] else []) ++
(if y > 0 then [5] else []) ++
(if x < a then [7] else []) ++
(if y < b then [9] else [])
(Old answer deleted.)
You have also an issue in the way you think if should be used. In Haskell if is an expression, i.e. it evaluates to a value. Because of this, it must always be accompanied by an else branch. Marcelo's example should clarify this. If you want something like the if statement in an imperative language, then you have Control.Monad.when or Control.Monad.unless.
There are a number of things wrong with your code, unfortunately. The first problem is the do on the top line: you aren't using any monads, so you shouldn't have it at all. The rest of the code is trying to work in an imperative manner, but this (unsurprisingly) doesn't work in Haskell. In Haskell, every expression needs to have a result; for this reason, all if statements must be of the form if ... then ... else .... Similarly, every let binding must be of the form let ... in ...; it's impossible to change the value of a variable, so if you left off the in, nothing would happen. And because of this, each line let result = result ++ [3], if it could be executed, would try to make a list result which consisted of all of its elements with a three at the end—in other words, a self-referential list! (The canonical example of such a thing is let ones = 1:ones in ones to create a list whose tail is itself and thus contains only 1s.)
So now the question is, what does your function want to do? You have four boolean conditions, and want to add a different element to your list for each one. There are a number of ways you could write this instead. One approach is
foo :: Integer -> Integer -> Integer
foo a b = let Coord x y = boo a b
checkAdd cond elem = if cond then (elem :) else id
in foldr (uncurry checkAdd) []
[(x > 0, 3), (y > 0, 5), (x > a, 7), (y > b, 9)]
First, we call boo and look at the results. We then define a checkAdd function, which has type checkAdd :: Bool -> a -> ([a] -> [a]). If its first argument is true, then it returns a function which prepends its second argument to a list; otherwise, it returns a function which does nothing to a list. So checkAdd True 1 x == 1:x, and checkAdd False 1 x == x. The last line is admittedly a little mysterious, but it's not too bad. If you have a list fns = [f1,f2,...,fn] of functions, and want to produce f1(f2(...(fn(x))...)), then you can use foldr ($) x fns. This fold is similar, except we have uncurry checkAdd instead of $; uncurry causes a function to take a tuple instead of two arguments, and so when we foldr it over the list, checkAdd produces a function for each element. Then, each function is applied, and you arrive at the list you wanted. The reason we don't have ($) . uncurry checkAdd is that $ is really just the identity function with low precedence; this makes sense, since $'s only purpose is to have really low precedence but not do anything.
Of course, this code looks completely different from what you had above, but that's part of what's interesting about trying out completely different languages :-)
This sort of append-output is very natural with the Writer monad.
import Control.Monad.Writer
foo a b = execWriter $ do
let Coord x y = boo a b
when (x > 0) $ tell [3]
when (y > 0) $ tell [5]
when (x < a) $ tell [7]
when (x < b) $ tell [9]
As already mentioned you are looking at this the wrong way. You can't change the value of an variable in Haskell, and if-then-else expressions always have an else clause. I have made some code that looks and feels like what you were trying to do, but as you have seen, there are many better ways of doing this.
foo a b = let Coord x y = boo a b in
(if x > 0 then (3 :) else id) .
(if y > 0 then (5 :) else id) .
(if x < a then (7 :) else id) .
(if x < b then (9 :) else id) $
[]

Resources