The topic of this post is the "argument appears on both sides so can drop it" steps. How do we go from passing foldl' a function which takes two explicit arguments (\arg x -> ...) to none? The answer is by using currying, partial function application and function composition, and we can do both of these in C# (albeit not as neatly, as C# is not really built for it).
At my work a few of us developers are learning Haskell, starting with some exercises from Tony Morris’s YOW workshop last year. One of these exercises involves re-implementing some common operations on lists, and this has proved a great way to learn some of the basics of Haskell.
For this post we’ll be working through implementing our own version of the length function, which takes a list and returns a integer reflecting the length of that list.
We’ll start with this non-functioning implementation, which we’ll call length' so it doesn’t collide with Haskell’s built-in function (' is a legal character to have in Haskell identifiers):
Being a bit of a realist (;)), I find it much easier to find problems with my design ideas than I do finding designs I’m really happy with. I am always cognisant of this and make sure to balance the needs of doing a good job and getting the job done. One technique I find useful for this is thinking about the minimum amount of code required.
Whenever I find myself evaluating different design patterns or counting responsibilities to work out where the feature should go or which areas I should refactor, I stop and work out the minimum amount of code I’d need to write to solve the problem, ignoring design considerations. Once I’ve starting thinking about the problem in that light, working out where to put that code becomes a bit easier. If the code violates my sense of design aesthetics, it could just be because it is a messy problem, and no matter how hard I try to abstract or design my way out, the fundamental messiness still remains.
One of the nice things about pure functional programming is that we can use mathematical properties and axioms to reason about, simplify and derive functions. A property that I’ve seen crop up a few times is associativity.
Bird and Wadler describe a strict function as one that is undefined when its input is undefined. The ⊥ symbol, or bottom, is used to represent ‘undefined’, so f is strict if f ⊥ = ⊥, otherwise it is non-strict.
This post is part 3 of a series on folds, which is my attempt to understand the topic. The examples are in Haskell, but hopefully you can follow along even if you’re not familiar with the language. If you find yourself getting lost in the syntax, I’ve written a Haskell quick start that goes through all the bits we’ll use.
In part 1 we found that a fold is a way of abstracting recursive operations over lists. In part 2 we saw that we could also express loops using recursion, which we could extract into a different type of fold. We learned that the loop-like fold is called a left fold (it accumulates its values on the left of the expression), and that our original fold was called a right fold (which accumulates to the right).
We saw we could implement several functions using both left and right folds (like sum, length, and mapFn). As both folds abstract away explicit recursion, they seem capable of producing the same results, just with different orders of evaluation. It turns out these differences in evaluation have some important implications, so in this post we’ll take a closer look at them.
This post is part 2 of a series on folds. Folds seem to crop up quite often in functional programing, and this series is my attempt to learn a little about the topic.
In part 1 we found that a fold is a way of abstracting recursive operations over lists. In this post we’ll look at a different way of folding; one that traverses lists in a similar way to a for/foreach loop.
Most software developers I know are really keen to improve their skills. But how do we know we’re improving? How can we tell if our efforts are effective? Without feedback on our progress, it is easy to feel swamped and demoralised by the rate at which stuff we want to learn piles up, compared with the rate at which we feel we’re improving. Setting and working towards goals can help address this.
Yet when I’ve asked other devs, most have great personal, work and non-tech goals, but have something to the effect of “become a better developer” thrown in as well. I’ve been thinking about this a bit recently, so thought I’d jot down a couple of thoughts about goals specifically related to software development.