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.
Related
I am trying to write a basic function in Haskell as shown below. My aim is provide the code to square only even numbers while odd numbers will stay same. Would you please help me regarding this issue.
square:: Int -> Int
square x = [ x*x | x <- [1..10], mod x 2 == 0 ]
regards
You are here filtering. You should determine if the number is even or odd and then square the number or not, this can be done in the yield part of the list comprehension.
But the type signature hints that you do not need to construct a list at all. You simply check if the parameter x is even, and if that is the case return x*x, otherwise return x:
square:: Int -> Int
square x = if even x then x*x else x
or through guards:
square:: Int -> Int
square x
| even x = x*x
| otherwise = x
One quite straightforward answer to your question is, you can inline a if statment directly into your list comprehension like so:
[ if even x then x * x else x | x <- [1..10] ]
This is possible since if is an expression in Haskell, meaning it evaluates to a value, so things like this are valid:
let _ = if 1 + 1 == 2 then "foo" else "bar"
It can also be good to look at this problem in another direction. List comprehensions can be quite nice, but sticking an if within it can get pretty messy. Willem's solution of factoring out the method is great, so let's look at other ways we can leverage it with your code:
-- This is the function we're trying to implement
evenSquares :: [Int] -> [Int]
-- We could start by noting that `if` expression has a nice name,
-- which can be factored out to make things look cleaner
-- Same implementation as Willem's
evenSquares xs = [ squareIfEven x | x <- xs ] where
squareIfEven x = if even x then x * x else x
-- List comprehensions are nice, but there's also another name for what we're doing,
-- which is mapping over a collection of values and applying a method
evenSquares xs = map squareIfEven xs where
squareIfEven x = if even x then x * x else x
-- Note how the `xs` is an argument to `evenSquares` and also the last argument to `map`
-- We can actually get rid of `xs` entirely via this rule:
-- https://wiki.haskell.org/Eta_conversion
evenSquares = map squareIfeven where
squareIfEven x = if even x then x * x else x
-- This one's a bit of a stretch, but conceptually quite useful
-- The idea of 'apply a method if a condition is true' can be expressed as a method
-- which takes a predicate method, a transformation method, and a value
-- We can leverage this ourselves to make `squareIfEven` more generic too
evenSquares = map (if' even square id) where
square x = x * x
if' pred fst snd x = if pred x then fst x else snd x
-- There's a bunch more solutions we can try, including things like `do` notation
-- This is just an idea of how you could look at your problem
-- Pick one which makes your solution clear and concise!
Is there any difference between
f x = x + 1
and
let f x = x + 1
when typed into GHCi? IIUC, there's a special rule that let without in inside GHCi effectively applies to the entire scope of the interpreter. But if the presence of let makes no difference, what's the point of this rule?
Edit: using GHCi version 8.0.2.
No, there's no difference.
It used to be that ghci was essentially an open-ended IO do block. But the inability to define new types in this syntax form, and the need to write let for every definition, were seen as annoying restrictions that often got in the way of everyday interactive use, and so the syntax of ghci has slowly become more permissive. But it is just a syntax change -- nothing deep.
However, there is one thing to be aware of: if you want to start a block, you must do that explicitly. For example,
> f [] = 3
> f (x:xs) = 4
is equivalent to
> let f [] = 3
> let f (x:xs) = 4
and not
> :{
| let f [] = 3
| f (x:xs) = 4
| :}
hence will be a new definition of f that shadows the old one and is only defined on non-empty lists, whereas you probably meant to give two equations for a single f. With automatic block mode (:set +m), ghci can notice that let started a block and automatically give you the latter when you type let, thus:
> let f [] = 3
| f (x:xs) = 4
|
It will not do this for short-form (non-let) definitions.
Although this question was asked months ago, I do notice some more difference when I start to learn Haskell recently.
> :set -Wall
> a = 2
> let a = 3
results in a warning about name shadowing (-Wname-shadowing), while
> :set -Wall
> a = 2
> a = 3
does not. It seems that the warning only checks for explicitly written let statements.
Another difference:
λ> x = 1 :: Int
λ> :sprint x
x = _
λ> let x = 1 :: Int
λ> :sprint x
x = 1
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.
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 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) $
[]