I was writing solutions to all the exercises in Haskell, when I basically hit a brick wall when Exercise 5 asks the student to “Write a chainable function that accepts one word per function call but, when called without arguments, will report back all the previously passed words in order.” In Haskell…
In case you are uninitiated, Haskell is a strongly-typed, purely-functional programming language, which implies that data types for functions’ inputs and outputs must be clearly defined, and furthermore that variables cannot be mutated in place. Exercise 5 asks us to write a function that can accept as input a string or nothing, and then will either produce an IO action or mutate(!) a running list of strings, depending on the type of the input.
I’m not saying that this can’t be done in Haskell—It totally can be done in Haskell.
It’s just that the notions of function in Haskell and function in other programming languages don’t exactly overlap.
Solving this problem in the most elegant way will involve clever use of the
State monad and the
IO monad and maybe even defining some of my own monads.
You can see my work in progress on my github repo.
The problem Exercise 5 poses makes much more sense in an object-oriented paradigm: I decided I’d write my Python solution first. Here was my first go:
Here, we define the global variable
words and the function
sayIt operates more or less how the problem statement requires, except for one detail: sayIt isn’t chainable.
In order to make it chainable, we need to (ed: can) make it a method of an object. If it returns itself upon method calls, then we can just dot subsequent method calls on the end. Here’s my second go:
When an instance of
Words is declared, it’s given an internal variable called
words which stores the current state, ie, the list of all the words that we’ve passed to the object via its sole method
_ has the behavior of
sayIt from above, but applies changes to the instance rather than to a global variable.
Thus, in the Python interactive prompt, we get the desired behavior: