How many times is (+ 1) computed here? - haskell

On my functional programming exam, I had the following question:
How many times is (+ 1) function computed in the following code?
(map (+ 1) [1 .. 10]) !! 5
where the index function is defined like this:
(h:_) !! 0 = h
(_:t) !! x = t !! (x-1)
I would say 6 times, but the correct answer seems to be 1, and I cannot understand why. I could not find a good enough explanation of lazy evaluation in Haskell, so I would like to know what is the correct answer and why. Thank you in advance!

many times is (+ 1) function computed in the following code?
It is calculated only once. map does not force to calculate f xi on the elements in the result list. These calculations are postponed (just like everything else in Haskell), only when we need to calculate the value of a specific item, we do that.
map is specified in chapter 9 of the Haskell'10 report as:
-- Map and append
map :: (a -> b) -> [a] -> [b]
map f [] = []
map f (x:xs) = f x : map f xs
There are no seq, bang patterns, etc. here to force evaluation of f x, so the map function will indeed "yield" an f x, but without evaluating f x, it is postponed until it is necessary (and it might happen that we are not interested in some of these values, and thus can save some CPU cycles).
We can take a look how Haskell will evaluate this:
(!!) (map (+ 1) [1 .. 10]) 5
-> (!!) ((+1) 1 : map (+1) [2..10]) 5
-> (!!) (map (+1) [2..10]) 4
-> (!!) ((+1) 1 : map (+1) [3..10]) 4
-> (!!) (map (+1) [3..10]) 3
-> (!!) ((+1) 1 : map (+1) [4..10]) 3
-> (!!) (map (+1) [4..10]) 2
-> (!!) ((+1) 1 : map (+1) [5..10]) 2
-> (!!) (map (+1) [5..10]) 1
-> (!!) ((+1) 1 : map (+1) [6..10]) 1
-> (!!) (map (+1) [6..10]) 0
-> (!!) ((+1) 6 : map (+1) [7..10]) 0
-> (+1) 6
-> 7
This is because map f [x1, x2, ..., xn] eventually maps to a list [f x1, f x2, ..., f xn], but it does not compute f xi of the elements, that computation is postponed until we actually would need the value in that list, and do something with it (like priting it).
This can result in a significant performance boost, given f is an expensive function, and we only need the value of a small amount of elements in the list.

Let's test it by doing something horrible. You'll need to import the Debug.Trace module for this.
ghci> (map (\x -> trace "Performing..." (x + 1)) [1..10]) !! 5
Now, we'll get that totally safe IO action to happen every time the lambda expression is called. When we run this in GHCi, we get
Performing
7
So only once.
As a sanity check, we could remove the !! 5 bit.
ghci> map (\x -> trace "Performing..." (x + 1)) [1..10]
[Performing
2,Performing
3,Performing
4,Performing
5,Performing
6,Performing
7,Performing
8,Performing
9,Performing
10,Performing
11]
So it's definitely happening 10 times when we ask for the whole list.

Related

for beginners | luhn algorithm for list of integers

I have already seen this solution:
doubleAndSum :: [Int] -> Int
doubleAndSum = fst . foldr (\i (acc, even) -> (acc + nextStep even i, not even)) (0,False)
where
nextStep even i
| even = (uncurry (+) . (`divMod` 10) . (*2)) i
| otherwise = i
myLuhn :: Int -> Bool
myLuhn = (0 ==) . (`mod` 10) . doubleAndSum . (map (read . (: ""))) . show
testCC :: [Bool]
testCC = map myLuhn [49927398716, 49927398717, 1234567812345678, 1234567812345670]
-- => [True,False,False,True]
However, I don't understand it because I am new to Haskell.
luhn :: [Int] -> Bool
luhn w x y z = (luhnDouble w + x + luhnDouble y + z) `mod` 10 == 0
luhnDouble :: Int -> Int
luhnDouble x | 2* x <= 9 = 2*x
| otherwise = (2*x)-9
I understand this simplified version of the algorithm for only four digits.
However, I don't know how to write a version of the algorithm for a list of digits of any length.
Honestly, the example is pretty arcane. It makes excessive use of point-free style, i.e. omitting explicit function arguments. That can sometimes make code nice and concise, but it can also make code rather cryptic.
Let's start with this here:
(uncurry (+) . (`divMod` 10) . (*2)) i
First, since you're just applying everything to the argument i, there's no real need for having a composition pipeline – you might as well write it
uncurry (+) $ (`divMod` 10) $ (*2) i
≡ uncurry (+) $ (`divMod` 10) $ i*2
≡ uncurry (+) $ (i*2)`divMod`10
≡ let (d,r) = (i*2)`divMod`10
in d+r
So, nextStep could be written
nextStep isEven i
| isEven = d+r
| otherwise = i
where (d,r) = (i*2)`divMod`10
(I avoid the variable name even, which is also the name of the standard function that checks whether a number is even!)
Alternatively, you could just invoke your luhnDouble function here, which actually computes the same thing, just in a more verbose way:
nextStep isEven i
| isEven = luhnDouble i
| otherwise = i
Then you have this fold. It basically does three things interlocked: 1. toggle between even and odd 2. apply nextStep to each list element, together with the even-ness 3. sum up the results.
I don't agree that it's a good idea to do all of that with a single fold†; much clearer to write it out:
doubleAndSum = sum
. map (\(isEven, i) -> nextStep isEven i) -- or `map (uncurry nextStep)`
. zip (cycle [False, True]) -- or `iterate not False`
. reverse
The reverse is needed just to align the False with the last element of the input list, instead of its head; this is a bit ugly but uncritical.
The combination of map and zip has a standard shortcut that does both in one step:
doubleAndSum = sum
. zipWith nextStep (cycle [False, True])
. reverse
As for myLuhn: this is IMO actually ok to write in the point-free style, but I'd break it out a bit. Specifically,
decimalDigits :: Int -> [Int]
decimalDigits = map (read . (: "")) . show
What (:"") does is, it puts single characters into singleton-strings. Could also be written read . pure.
Then,
myLuhn = (0 ==) . (`mod` 10) . doubleAndSum . decimalDigits
or
myLuhn x = doubleAndSum (decimalDigits x)`mod`10 == 0
†There could be a case made that a single traversal is good for performance, however if you think on that level then it should almost certainly not be a lazy right fold over a list, but rather a strict left fold over an unboxed vector. Anyway, GHC can often fuse separate fold-y operations into a single traversal.

Fibonacci Bit Representation Haskell

I already have the following functions
toBin, auxBin :: Integer -> [Integer]
toBin 0 = [0]
toBin n = reverse (auxBin n)
auxBin 0 = []
auxBin n = n `mod` 2 : auxBin (n `div` 2)
fib :: Int -> Integer
fib n = fibs !! n
where
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
fibonacci = [fib n | n <- [0..]]
But when I map the Fibonacci list with the toBin function, I obtained an incorrect list:
Becuase, I obtained this:
[[0],[1],[1],[1,0],[1,1],[1,0,1],[1,0,0,0],[1,1,0,1],[1,0,1,0,1],[1,0,0,0,1,0]]
But, I want this:
[0,1,10,101,1010,10101,101010,1010101,10101010,101010101]
Could you help me?
There are many ways to add digits together in order to get a number. Here's one way. Probably not the most efficient way, but on the other hand built up from smaller functions.
Values like [1,0,1],[1,0,0,0], and [1,1,0,1] are lists in their own right, so what we can do first is to index them. The only trouble is that we'd like to index them in descending order. You can do that by reversing them, indexing them, and then reverse them again, e.g.:
Prelude> reverse $ zip [0..] $ reverse [1,1,0,1]
[(3,1),(2,1),(1,0),(0,1)]
The first element in each tuple is the order of magnitude, so you just need to make it a power of ten:
Prelude> :m +Data.Bifunctor
Prelude Data.Bifunctor> reverse $ fmap (first (10 ^)) $ zip [0..] $ reverse [1,1,0,1]
[(1000,1),(100,1),(10,0),(1,1)]
Now you can simply multiply the elements of the tuples together:
Prelude Data.Bifunctor> reverse $ fmap (uncurry (*) . first (10 ^)) $ zip [0..] $ reverse [1,1,0,1]
[1000,100,0,1]
Finally, you can add all of those numbers together. In fact, you don't need to reverse the reversed list:
Prelude Data.Bifunctor> sum $ fmap (uncurry (*) . first (10 ^)) $ zip [0..] $ reverse [1,1,0,1]
1101
You can put such a combination in a function and map your values over it.
A more efficient solution would probably be to just be to do a left fold (foldl), e.g.:
Prelude> foldl (\acc x -> (10 * acc) + x) 0 [1,1,0,1]
1101
Prelude> foldl (\acc x -> (10 * acc) + x) 0 [1,1,1]
111
An idea could be to represent binary values in decimal notation. So we "transform" 2 into 10.
We can do that by writing a recursive function:
bintodec :: Integral i => i -> i
bintodec 0 = 0
bintodec i = (mod i 2) + 10 * bintodec (div i 2)
This only works for positive values, but that is not really a problem here, since Fibonacci numbers are positive numbers.
Now we already have a definition of the Fibonacci numbers, like in your answer:
fibs :: Num n => [n]
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
So the only thing we still have to do is map every elements of fibs with bintodec:
binfibs :: Integral i => [i]
binfibs = map bintodec fibs
The first 15 numbers are then:
Prelude> take 15 binfibs
[0,1,1,10,11,101,1000,1101,10101,100010,110111,1011001,10010000,11101001,101111001]
The nice thing is here that we do not use any binary lists to process it, but keep working in the integer world, which is usually more safe.
Based on the second list however, this has nothing to do with Fibonacci numbers. There you start with 0, and you then shift a zero or a one in at the right end of the number.
We can use iterate for this:
iterate (\x -> 10 * x + 1-(mod x 2)) 0
which produces:
Prelude> take 15 $ iterate (\x -> 10 * x + 1-(mod x 2)) 0
[0,1,10,101,1010,10101,101010,1010101,10101010,101010101,1010101010,10101010101,101010101010,1010101010101,10101010101010]

How is $ used in higher order functions ? [duplicate]

This question already has answers here:
Why is `($ 4) (> 3)` equivalent to `4 > 3`?
(3 answers)
Closed 7 years ago.
This concerns an example encountered in Learn you a Haskell for Great Good, namely this one :
ghci> map ($ 3) [(4+), (10*), (^2), sqrt]
I'm trying to understand it but it makes no sense to me. Of course, the list of functions will be applied to the input (number 3) but I don't see how the $ operator helps. I'm trying to trace the order of application of things (if there's a haskell IDE with a step through compiler please let me know) and can't understand how $ being right associative allows flipping the function application, ie when I see map like this
map fun [1, 2 .. n]
I imagine the following happening to form the output list
fun 1
fun 2
.
.
fun n
but for the example at hand, how is this of meaning :
$3 4+
how is this of meaning :
$3 4+
That's not actually of meaning, indeed. But that's not what it simplifies to! It simplifies to
($3) (4+)
These things are operator sections.
($ 3) ≡ \x -> x $ 3
(4+) ≡ \x -> 4 + x
(10*) ≡ \x -> 10*x
(^2) ≡ \x -> x^2
so
($3) (4+) ≡ (\f -> f $ 3) (\y -> 4 + y)
≡ (\y -> 4 + y) $ 3
≡ (\y -> 4 + y) 3
≡ 4 + 3
Perhaps it's easier to understand if you visualise the “holes”:
map (□ $ 3) [(4+□), (10*□), (□^2), sqrt □]
≡ [(4+□) $ 3, (10*□) $ 3, (□^2) $ 3, (sqrt □) $ 3]
≡ [(4+3), (10*3), (3^2), (sqrt 3)]
The operator $ calls the function which is its left hand argument on the value which is its right hand argument. In the use of the example it "puts" the value 3 as additional argument of the sections in the list
Thus ($ 3) (4+) is (4+3). Analogously ($ 2) (4/) is (4/2)
The use of sections is easier to grasp using normal arithmetic operations. For instance: (/2) 4 is the same as 4/2 and thus 2

Define function in Haskell using foldr

I'm trying to define a function in Haskell using the foldr function:
fromDigits :: [Int] -> Int
This function takes a list of Ints (each on ranging from 0 to 9) and converts to a single Int. For example:
fromDigits [0,1] = 10
fromDigits [4,3,2,1] = 1234
fromDigits [2,3,9] = 932
fromDigits [2,3,9,0,1] = 10932
Anyway, I have no trouble defining this using explicit recursion or even using zipWith:
fromDigits n = sum (zipWith (*) n (map ((^)10) [0..]))
But now I have to define it using a foldr, but I don't know how to get the powers of 10. What I have is:
fromDigits xs = foldr (\x acc -> (x*10^(???)) + acc) 0 xs
How can I get them to decrease? I know I can start with (length xs - 1) but what then?
Best Regards
You were almost there:
your
fromDigits xs = foldr (\x acc -> (x*10^(???)) + acc) 0 xs
is the solution with 2 little changes:
fromDigits = foldr (\x acc -> acc*10 + x) 0
(BTW I left out the xs on each sides, that's not necessary.
Another option would be
fromDigits = foldl (\x acc -> read $ (show x) ++ (show acc)) 0
The nice thing about foldr is that it's so extemely easy to visualise!
foldr f init [a,b, ... z]
≡ foldr f init $ a : b : ... z : []
≡ a`f b`f`... z`f`init
≡ f a (f b ( ... (f z init)...)))
so as you see, the j-th list element is used in j consecutive calls of f. The head element is merely passed once to the left of the function. For you application, the head element is the last digit. How should that influence the outcome? Well, it's just added to the result, isn't it?
15 = 10 + 5
623987236705839 = 623987236705830 + 9
– obvious. Then the question is, how do you take care for the other digits? Well, to employ the above trick you first need to make sure there's a 0 in the last place of the carried subresult. A 0 that does not come from the supplied digits! How do you add such a zero?
That should really be enough hint given now.
The trick is, you don't need to compute the power of 10 each time from scratch, you just need to compute it based on the previous power of ten (i.e. multiply by 10). Well, assuming you can reverse the input list.
(But the lists you give above are already in reverse order, so arguably you should be able to re-reverse them and just say that your function takes a list of digits in the correct order. If not, then just divide by 10 instead of multiplying by 10.)

Alternative way of creating a list than a comprehension?

Currently I am doing something like this in my code:
--Generate a list of n 'Foo's
generateFoos n = [createFoo (show i) | i <- [1..n]]
-- Create a Foo with a given name
createFoo :: String -> Foo
I was wandering if there is a another way of doing this than creating a range [1..n] all the time...
I would say don't worry about it. "Creating the range [1..n]" isn't really going on here as a distinct step; that [1..n] desugars to enumFromTo 1 n and it's constructed lazily like everything else anyway. There's no hidden cost here one would need to eliminate.
Expanding on my comment above - the reason the map function arises naturally here is as follows.
In Haskell, list comprehensions are just syntactic sugar for do notation:
[ 2 * x | x <- [1..10] ]
is equivalent to
do { x <- [1..10]; return (2 * x) }
In turn, do notation is syntactic sugar for monadic binds - the above is equivalent to
[1..10] >>= \x -> return (2 * x)
This works because List is a monad. The code that makes List into a monad is (ignoring some irrelevant stuff)
instance Monad [] where
return x = [x]
xs >>= f = concat (map f xs)
so the call to >>= above is equivalent to
concat (map (\x -> return (2 * x)) [1..10])
which, if we replace the call to bind, is equivalent to
concat (map (\x -> [2 * x]) [1..10])
So we map the function \x -> [2 * x] over the list [1..10] and then call concat on the result. But since our function only every builds one element lists, we can skip out the call to concat and replace the code with
map (\x -> 2 * x) [1..10]
So it's natural that relatively simple list comprehensions can be turned into expressions that involve mapping a function over a range.
I prefer it that way:
generateFoos n = map (createFoo . show) [1..n]
Or are the ranges itself the problem? Then I'd recommend:
generateFoos n = map (createFoo . show) (enumFromTo 1 n)
No map, no range.
generateFoos n = unfoldr (doit (createFoo . show)) 1 where
doit f acc = if acc > n then Nothing else Just (f acc, acc + 1)
I do not guarantee any particular quality or property of this code though ;)

Resources