We were recently lucky enough to have Tomas Petricek on site to give us a special workshop on Expressing Intent with F#. Tomas works with the F# Microsoft Research Team in London and is an active F# open-source contributor.
Much of the power of F# comes from the fact that it can model the domain that we are working with in a simple and composable way that makes invalid states unrepresentable. In this workshop, I’ll go through a variety of instances of this principle. The idea of using algebraic data types (records and unions) for expressing business logic is well-known, but we can go beyond that and discover the same pattern in function composition, parsing libraries, machine learning, and also libraries for asynchronous and reactive programming.
Tomas outlined some important topics when it came to expressing intent:
- Understand what code means
- Build complex logic from simple logic
- Compose correct code from correct blocks
- Use types to enforce correctness
As part of the workshop, we broke into teams with each team working on one of the following projects:
- Decision trees
- Asynchronous sequences
- Markdown parsing
- Pattern recognition in a line graph
The projects all consisted of a completed base, which Tomas reviewed in his presentation in the first half of the workshop, and then two or three tasks which involved extending the functionality of the base project. Each task required an understanding of how the base logic worked in F#.
In the last part of the workshop, we worked with our teams to complete the project tasks while Tomas worked with individuals or teams to help them finish their tasks. Tomas’s help ranged from giving advice on how to get started on a task, how to fix bugs we ran into, all the way to helping people who had completed tasks come up with more elegant solutions.
I worked on the decision tree project, where the logic for constructing the decision tree from a sample of an existing dataset had already been completed. A decision tree is an algorithm for classifying an entity based upon measurements of specific features (e.g. classifying a type of flower using the length of its petals, and its color. In this case, the features are: petal length and color). The tasks then were: 1. validating the accuracy of the decision tree and 2. expanding it to allow for features that are categorical rather than continuous (length of a petal is a continuous feature and gender is categorical).
Working on this project with my team, I helped some of the new hires who were unfamiliar with F# get comfortable with how to express certain ideas in F# along with how to approach the problems in a more functional way. I focused mostly on how to come up with a more elegant solution to how to apply the decision tree to a data sample and categorize it. The design we started with felt slightly clunky, and I talked with Tomas a bit about how to have a more streamlined implementation. This was great because it let me focus specifically on the quality of my own written code and think about what patterns and strategies can help me design structures which produce simple and clear code.
A big thanks to Tomas for visiting Jet!