Haskell and F# – Advent of Code Day 1

This is the first in a series of occasional posts comparing Haskell and F# when solving the 2018 Advent of Code puzzles (AoC). One puzzle is available on each of the 25 days of December leading up to the 25th. Each puzzle is in two parts and the second part is only available once the first part has been solved!

I’ve been learning Haskell for a few years now – I ‘got’ monads about a year ago then thought ‘oh duh!’ . My knowledge of F# is embryonic – I’ve only just started – and I thought it might be informative to solve some problems using both languages.

Day 1. Part 1

Reduces to reading in a list of integers, positive and negative and summing them. Full details are here.

In Haskell…

In Haskell reading in a file is done monadically in the IO Monad. For AoC last year I made a small library of parser utilities to help in reading a file of ints or strings etc. This function is at the core of it

Just give withData a suitable parser and it will return a parsed data in the IO Monad. A suitable parser can be easily constructed in an applicative style like this

Which will parse from a newline separated file of strings to a list of ints with the strings having an explicit ‘+’ char rather than an assumed positive sign. i.e. +4 rather than 4. I wrote the above just for the fun of applicative parsing and really a simpler way is to use readFile then the lines function and finally map a read over everything whilst handling the wrinkle of an explicit ‘+’ which confuses read. Like this

Once the input has been obtained the solution is very much a one-liner! (Well, two if the function signature is included).

In F#…

Reading from the input file and parsing it as a list of integers was slightly simpler in F# as there’s no need to handle the ‘+’ char as a special case. And using the pipeline operator we can write:

Here the individual numbers (strings) are mapped over with the int function and are then summed. A very simple one liner!

Part 2.

Part two involved repeatedly summing the data in the list, taking each entry in turn, and looking for the first running total to appear twice. If the end of the list is reached then continue again from the start. Again, see here.

In Haskell…

The code is quite simple and a Map is used to maintain the individual running totals as they occur (key and value being the same). As soon as the current total is seen to be already in the Map then it terminates. i.e.

The search starts with an empty map and repeatedly generates the next total using the itemAt function which does list lookup modulo the length of the list. The search terminates when the current total is already in the map.

In F#…

The F# version is pretty much the same.

Well, that’s about it! My initial impressions of F# are essentially positive. It is slightly more verbose than Haskell – especially the function signatures. To be honest I’m glad I learnt Haskell before F# because Haskell enforces a disciplined way of coding. F# offers easy access to imperative style idioms and Haskell makes such crutches slightly difficult to use.

I did solve the problems in F# before using Haskell in an attempt to not just convert Haskell to F#. Being a beginner in F# I would think what I have is perhaps not too idiomatic but the idioms, with experience and learning, should come.

Thanks for reading and all the code is here (Haskell) and here (F#).




1 comment

Leave a Reply

Your email address will not be published. Required fields are marked *

ˆ Back To Top