Today was a Haskell day. My current endeavors include foldr and foldl, and believe me: the going got tough.
One thing that confused me is the following:
Prelude> foldr const 0 ([1..3] ++ undefined)
(Note that simply concatenating undefined to a list throws an error, because the list - in its entirety - is evaluated, and the (++) function requires two list arguments.)
(Also note that const takes two arguments and returns the first argument.)
(Also also note that foldr works like so:
foldr f z (x:xs) = f x (foldr f z xs))
Let’s name our list ([1..3] ++ undefined) lst. Here is what happens first:
foldr const 0 lst = const (head lst) (foldr const 0 (tail lst))
Since the const function just ignores the second argument, 1 is returned.
But, when I wrote this out on paper, I was getting so confused:
(const 1 (const 2 (const 3 (const undefined 0))))
Why doesnt ‘const undefined 0’ throw an error? Because it is never evaluated as the outer most parentheses are evaluated first, and const just ignores the second argument (bold for emphasis).
As for foldl:
Prelude> foldl const 0 ([1..3] ++ undefined)
>*** Exception: Prelude.undefined
>CallStack (from HasCallStack):
> error, called at libraries/base/GHC/Err.hs:78:14 in base:GHC.Err
> undefined, called at
This doesn’t work!
Here’s how it is written out on paper:
((((1 `const` 0) `const` 2) `const` 3) `cons` undefined)
Here, the outermost parentheses contain undefined, and therefore an error is thrown. (I put the `` around const to make it an infix operator for visual purposes. Otherwise, the expansion looks similar to that of foldr).
This really confused me. I was thinking: How does foldr know where the end of the list is without having to evaluate the undefined part and foldl doesn’t? How does foldr know when to stop looking for more elements in the list and foldl doesn’t?
But after some help from Lewis, Frank, Francesco, and Daniel (and God (kidding)), it all makes sense. It was funny to see the confusion this question caused, but it thankfully came to a resolution 😄
Tomorrow I will (start my day at the Ausländerbehörde at 7:30*, then) implement some functions (which I already completed with recursion) using folds such as myOr (a function that applies logical or to a list of booleans), myAny (a function that returns whether or not some value in a list meets a certain condition), and squish (which flattens a list of lists into one list). It will be pretty tough to get out of the recursive mindset and implement these functions with folds, but I’m sure I’ll come out alive 😅
I will also do some research on the testing pyramid and Docker (whether that be using online or human sources).
Signing off! 👋
* When I was at the Ausländerbehörde the other day, I ended up waiting in the wrong line for 1.5 hours, only to get to the correct place for Blue Card applications and be told that there were no more spots for the day. At first I was really upset and annoyed that I couldn’t get an appointment, but now I realize that maybe it was a blessing because, in said correct place, I saw people wearing suits, and I was wearing running shorts and a t-shirt.