Thursday, June 27, 2019

A flashback and analogy

You've probably heard about how the notion of sum types (e.g. Algol 68 unions, Rust enums, Haskell types) and product types (e.g. tuples or structs) generalizes, e.g. [a] can be thought of as ${a^0} + {a^1} + {a^2} + {a^3} + ...$ where the exponent corresponds to the length of the list.

This morning I had a flashback from that to my days in introductory numerical analysis and Taylor series, Chebyshev polynomials, and other infinite bases for function spaces. Just as evaluating, e.g., exp(x) can be done by evaluating the first N terms of the corresponding Taylor series where N may vary depending on x but is nonetheless finite, in Haskell, as long as you only evaluate finitely many elements of an "infinite" list, you can do what you need to do.

Friday, June 21, 2019

I wish I were a dog

As I've mentioned recently, I'm now in a Meetup for people in the Des Moines, IA area where we're seriously doing the problems and paying close attention to the text, so I noticed this function intended to map your dog's age in years to a corresponding age in people years, while also introducing the beginning Haskell programmer to guards:

dogYrs :: Integer -> Integer
dogYrs x
   | x <= 0    = 0
   | x <= 1    = x * 15
   | x <= 2    = x * 12
   | x <= 4    = x * 8
   | otherwise = x * 6

Looking at it, you can see that yes, dogs mature faster than people but the rate tapers off with increasing age (but still faster than people). OK...but then something looked wrong. A function like this ought to be monotonically increasing, right?

map dogYrs [0..5]
[0, 15, 24, 24, 32, 30]

So dogs don't age in human years between 2 and 3, and get younger in human years between 4 and 5? (If myDog took and returned types in Fractional, things would get even weirder, because then dogs would celebrate their second birthday plus epsilon by getting almost three years younger in human years, and their fourth birthday plus epsilon by getting almost eight years younger in human years.)

As a human, I feel cheated. As a person looking to get better at Haskell, I think I'd better write a quickCheck test that a function is monotonically increasing.

Monday, June 10, 2019

"Assignment" versus parameter passing

It's been a while. Still looking for work, but I'm happy to say that there is now a Des Moines area meetup for people learning Haskell, so that I'm going through Haskell Programming from First Principles more seriously this time and doing all the exercises.

Thanks to that, I realize that one can express the one well-behaved function of type a -> b -> a as curry fst, but I am confused by one problem (so far). It's the first of a set that has the student modify a type signature and see how it affects the binding of a particular expression to the variable whose type signature is changed. Initially we have

i :: Num a => a
i = 1

and the change is to

i :: a
i = 1 

The first one clearly works; Num a => a is the type of numerical constants (without decimal points) in Haskell. The second, if you try it, fails, with ghci nudging you to put back the typeclass constraint... but at this point my time working on compilers comes back to me, and I recall the following: semantically, passing a parameter to a function is assignment. You assign the actual parameter to the corresponding formal parameter (really, you put it where the ABI says the parameter should go for the called function to get to it).

So... if you can't assign 1 to i when i's type signature is a, why can you pass 1 to id? Haskell must treat the two differently. Looks like I just have to find out what the difference is.

Riddler Classic, May 23, 2020—Holy Mackerel!

Another one using Peter Norvig's word list . It turns out that the word "mackerel" has a curious property: there is exactly ...