Why the haskell map does not work with (-1)? [duplicate] - haskell

This question already has answers here:
What is the equivalent to (+1) for the subtraction, since (-1) is seen as a negative number? [duplicate]
(3 answers)
Closed 1 year ago.
What was wrong with the following code?
map (+1) [1, 2, 3 ] == map (\x -> x + 1) [1, 2, 3]
map (1+) [1, 2, 3] == map (\x -> 1 + x) [1, 2, 3]
map (-1) [1, 2, 3] == map (\x -> x - 1) [1, 2, 3]
map (1-) [1, 2, 3] == map (\x -> 1 - x) [1, 2, 3]
Why the following does not work?
map (-1) [1, 2, 3]

(-1) is interpreted as a number: minus one. You can use subtract :: Num a => a -> a -> a to subtract a value:
map (subtract 1) [1, 2, 3] == map (\x -> x - 1) [1, 2, 3]

Related

How to express a foldl-based code with foldr?

I am attempting to convert a list of integers into a single integer using the foldr function. I have seen implementations that use the foldl function but am trying to figure out how to do the same thing using foldr.
The output should look something like:
list2int [0,1,2,3,0,4,5]
>123045
My code:
list2int :: [Int] -> Int
list2int = foldr (\x acc -> acc*10 + x) 0
However, when I run the code above using the same input, it returns 5403210. .
I don't really recommend this, but it exists.
ghci> foldr (\x k acc -> k $! (10 * acc + x)) id [0,1,2,3,0,4,5] 0
123045
The reason I don't recommend it is that it's roughly the same thing as inlining the definition of foldl', but harder to read.
And this is really a problem that should use foldl' to solve. It associates the operation the correct direction and has the correct strictness. Problems like this are the whole reason it exists.
Let's run through what happens with your function when you fold over [0, 1, 2, 3, 4, 0, 5]:
foldr (\x acc -> acc*10 + x) 0 [0, 1, 2, 3, 4, 0, 5]
foldr (\x acc -> acc*10 + x) 5 [0, 1, 2, 3, 4, 0]
foldr (\x acc -> acc*10 + x) 50 [0, 1, 2, 3, 4]
foldr (\x acc -> acc*10 + x) 504 [0, 1, 2, 3]
foldr (\x acc -> acc*10 + x) 5043 [0, 1, 2]
foldr (\x acc -> acc*10 + x) 50432 [0, 1]
foldr (\x acc -> acc*10 + x) 504321 [0]
foldr (\x acc -> acc*10 + x) 5043210 []
5043210
But what if we provide foldr with a tuple, containing our accumulator, and a base to multiply each digit by?
Our initial value will be a base of 1 and an accumulator of 0: (1, 0). Each time through, we'll multiply the base by 10.
Prelude> foldr (\x (base, acc) -> (base * 10, acc + x * base)) (1, 0) [0, 1, 2, 3, 0, 4, 5]
(10000000,123045)
Prelude>
Now, consider what happens:
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (1, 0) [0, 1, 2, 3, 0, 4, 5]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (10, 5) [0, 1, 2, 3, 0, 4]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (100, 45) [0, 1, 2, 3, 0]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (1000, 45) [0, 1, 2, 3]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (10000, 3045) [0, 1, 2]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (100000, 23045) [0, 1]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (1000000, 123045) [0]
foldr (\x (base, acc) -> (base * 10, acc + x * base)) (10000000, 123045) []
(10000000, 123045)
This basic pattern of using a tuple to pass state through iterations of a fold may be useful to you in the future.
Now we just need to extract the second number in this tuple, and you have the desired result.
It's also possible to pass the base, and multiply the current number by 10 raised to that base, starting with a base power of 0.
Prelude> foldr (\x (basePow, acc) -> (basePow + 1, acc + x * 10 ** basePow)) (0, 0) [0, 1, 2, 3, 0, 4, 5]
(7.0,123045.0)
Prelude>
Credit to Will Ness for pointing out the most elegant solution to this problem with foldl. The above demonstration of foldr is just one approach to solving this problem. Hopefully viewing multiple approaches to solving the same problem will be instructive.
Using your code with [0, 1, 2, 3, 4, 0, 5] works as
foldr (\x acc -> acc*10 + x) 0 [0, 1, 2, 3, 4, 0, 5]
= {- it's easier to see this way: -}
foldr (\x acc -> x + 10*acc) 0 [0, 1, 2, 3, 4, 0, 5]
=
0 + 10*(1 + 10*(2 + 10*(3 + 10*(4 + 10*(0 + 10*(5 + 10*(0)))))))
We just replace each , (and the ending bracket) in the list with + 10*(, put the 0 in the end, and balance the parens. That is what foldr is doing.
So this treats the lists as starting with the least significant digit, instead of the most significant, as they actually are.
The correct way to express this is with the left fold,
foldl (\acc x -> acc*10 + x) 0 [0, 1, 2, 3, 4, 0, 5]
=
(((((((0)*10 + 0)*10 + 1)*10 + 2)*10 + 3)*10 + 4)*10 + 0)*10 + 5
Again, we just replace each , (and the opening bracket) in the list with )*10 + , put the 0 in the front, and balance the parens. And that's what foldl is doing.
For reasons of efficiency, as mentioned in the answer by Carl, foldl' should be used here instead of foldl (which is usually the case).
To still be doing this with foldr, it must be composed with reverse:
foldr (\x acc -> acc*10 + x) 0 . reverse $ [0, 1, 2, 3, 4, 0, 5]
and when you write out reverse as a right fold and compose the two folds into one you'll probably end up with the version shown in Carl's answer. Could be a nice exercise to work through.

How I make result a list of booleans

I have this:
getMask (/= 3) [1, 2, 3, 4, 5]
and result must be this:
[True, True, False, True, True]
i tried something like this
getMask p xs = [x | (x,m) <- enumerate xs, if p x then True else False]
but i get only numbers. I need list of booleans
You can use map :: (a -> b) -> [a] -> [b]:
> map (/= 3) [1, 2, 3, 4, 5]
[True,True,False,True,True]
or a simple list comprehension:
getMask p xs = [p x | x <- xs]

Haskell what does ++ do

What does "++" do? I tried looking it up, but couldn't find anything.
It's list concatenation.
(++) :: [a] -> [a] -> [a]
[1, 2, 3] ++ [4, 5, 6] == [1, 2, 3, 4, 5, 6]
See https://www.haskell.org/onlinereport/haskell2010/haskellch9.html#x16-1720009.1

How to split a list into two in Haskell? [duplicate]

This question already has answers here:
Simple haskell splitlist
(3 answers)
Closed 6 years ago.
I'm trying to split a list into two so that when the input is
[1,2,3,5,6]
output would be
[1,2,3][5,6]
but I can't seem to figure it out.
The best I can do is [1,3,6][2,5].
I am a beginner. So, please correct me if this is wrong or sub-optimal.
internalSplit :: [a] -> Int -> [a] -> [[a]]
split :: [a] -> [[a]]
internalSplit (first:rest) count firstPart
| count == 0 = [firstPart, (first:rest)]
| otherwise = internalSplit rest (count - 1) (firstPart ++ [first])
split myList =
let listLength = length myList
in
if listLength `mod` 2 == 0 then
internalSplit myList (listLength `div` 2) []
else
internalSplit myList ((listLength `div` 2) + 1) []
main = do
print $ split [1, 2, 3, 5, 6]
print $ split [1, 2, 3, 4, 5, 6]
Output
[[1,2,3],[5,6]]
[[1,2,3],[4,5,6]]
Edit:
Managed to use builtin functions and came up with this
internalSplit :: [a] -> Int -> [[a]]
split :: [a] -> [[a]]
internalSplit myList splitLength = [(take splitLength myList), (drop splitLength myList)]
split myList =
let listLength = length myList
in
if listLength `mod` 2 == 0 then
internalSplit myList (listLength `div` 2)
else
internalSplit myList ((listLength `div` 2) + 1)
main = do
print $ split [1, 2, 3, 5, 6]
print $ split [1, 2, 3, 4, 5, 6]
Output
[[1,2,3],[5,6]]
[[1,2,3],[4,5,6]]
Edit 1:
internalSplit :: [a] -> Int -> ([a], [a])
split :: [a] -> ([a], [a])
internalSplit myList splitLength = splitAt splitLength myList
split myList =
let listLength = length myList
in
if listLength `mod` 2 == 0 then
internalSplit myList (listLength `div` 2)
else
internalSplit myList ((listLength `div` 2) + 1)
main = do
print $ split [1, 2, 3, 5, 6]
print $ split [1, 2, 3, 4, 5, 6]
Output
([1,2,3],[5,6])
([1,2,3],[4,5,6])
Edit2
As suggested by Bogdon in the comments section, this can be greatly simplified to this
split :: [a] -> ([a], [a])
split myList = splitAt (((length myList) + 1) `div` 2) myList
main = do
print $ split [1, 2, 3, 5, 6]
print $ split [1, 2, 3, 4, 5, 6]
Output
([1,2,3],[5,6])
([1,2,3],[4,5,6])

Understanding the functions elem and isInfixOf

A while ago I've asked a question about the function elem here, but I don't think the answer is fully satisfactory. My question is about the expression:
any (`elem` [1, 2]) [1, 2, 3]
We know elem is in a backtick so elem is an infix and my explanation is:
1 `elem` [1, 2] -- True
2 `elem` [1, 2] -- True
3 `elem` [1, 2] -- False
Finally it will return True since it's any rather than all. This looked good until I see a similar expression for isInfixOf:
any (isInfixOf [1, 2, 3]) [[1, 2, 3, 4], [1, 2]]
In this case a plausible explanation seems to be:
isInfixOf [1, 2, 3] [1, 2, 3, 4] -- True
isInfixOf [1, 2, 3] [1, 2] -- False
I wonder why they've been used in such different ways since
any (elem [1, 2]) [1, 2, 3]
will give an error and so will
any (`isInfixOf` [[1, 2, 3, 4], [1, 2]]) [1, 2, 3]
Your problem is with the (** a) syntactic sugar. The thing is that (elem b) is just the partial application of elem, that is:
(elem b) == (\xs -> elem b xs)
However when we use back ticks to make elem infix, we get a special syntax for infix operators which works like this:
(+ a) == (\ b -> b + a)
(a +) == (\ b -> a + b)
So therefore,
(`elem` xs) == (\a -> a `elem` xs) == (\ a -> elem a xs)
while
(elem xs) == (\a -> elem xs a)
So in the latter case your arguments are in the wrong order, and that is what is happening in your code.
Note that the (** a) syntactic sugar works for all infix operators except - since it is also a prefix operator. This exception from the rule is discussed here and here.
Using back-ticks around a function name turns it into an infix operator. So
x `fun` y
is the same as
fun x y
Haskell also has operator sections, f.e. (+ 1) means \x -> x + 1.
So
(`elem` xs)
is the same as
\x -> x `elem` xs
or
\x -> elem x xs
or
flip elem xs
It's called partial application.
isInfixOf [1, 2, 3] returns a function that expects one parameter.
any (elem [1, 2]) [1, 2, 3] is an error because you're looking for an element [1, 2], and the list only contains numbers, so haskell cannot match the types.

Resources