My primary experience with functional programming is my college’s CS151 course, which is taught in Typed Racket. Recently, I’ve done a bit of exploring into Haskell; so far, I’ve read a bit of Learn You A Haskell, and I’ve reimplemented some of CS151’s homework assignments in Haskell. It’s been an interesting experience, so I’ve written up my initial thoughts on the differences between the two languages. I’m planning on turning this into a series as I learn more Haskell, so stay tuned!.

**Disclaimer**: this post will contain solutions to some of the problems from
UChicago’s 2016 winter-quarter CS151. If you are in a future version of this
class, please click away.

## Season 1: Homebrew Peano Numbers

One of our assignments was to write a simple implementation of Peano numbers, complete with conversion, addition, saturating subtraction, multiplication, and comparison functions. But before we do any of those, let’s first define the type we’ll be working with. In Racket:

```
(define-type Nat (U 'Zero Suc))
(define-struct Suc ([prev : Nat]))
```

And in Haskell:

```
data Nat = Zero | Suc Nat deriving (Show, Eq)
```

### Conversions

First, let’s look at the simple conversion functions between our `Nat`

s and
regular integer representations. In Racket:

```
(: nat->num : Nat -> Integer)
(define (nat->num n) (cond
[(Suc? n) (+ 1 (nat->num (Suc-prev n)))]
[else 0]))
(: num->nat : Integer -> Nat)
(define (num->nat n) (cond
[(not (zero? n)) (Suc (num->nat (sub1 n)))]
[else 'Zero]))
```

And in Haskell:

```
nat_to_num :: Nat -> Natural
nat_to_num Zero = 0
nat_to_num (Suc n) = 1 + nat_to_num n
num_to_nat :: Natural -> Nat
num_to_nat 0 = Zero
num_to_nat n = Suc (num_to_nat (n - 1))
```

Easy enough. These were the first two functions I wrote in Haskell, so a bunch of things immediately jumped out at me.

- I
*love*how you can just have your base case be an additional line. I like how it’s analogous to solving a system of equations. Very cool syntax, and probably much more powerful than I know right now. Also eliminates lots of`cond`

s and`match`

es in Racket that only check one edge case. - Why does Haskell have such restrictive rules on symbols in function names? From the Haskell wiki:

Variable identifiers start with a lowercase letter, constructor identifiers with an uppercase letter and both can contain underscores, single quotes, letters and digits. Operators are formed from one or more of

`'!#$%&\*+./<=>?@\^|-~'`

. Constructors can be operator names, so long as they start with a ‘`:`

’ (e.g.,`:+`

for`Data.Complex`

).

That seems markedly worse than Racket’s “you can call your function
`A+->=_*^%`

for all I care” approach.
3. I love Racket’s treatment of symbols (i.e. `'Zero`

). There doesn’t seem to be
an analog for that in Haskell.

### Arithmetic

Let’s examine the addition and multiplication functions. In Racket:

```
(: nat+ : Nat Nat -> Nat)
(define (nat+ i j) (match* (i j)
[(_ 'Zero) i]
[('Zero _) j]
[((Suc _) (Suc jprev)) (nat+ (Suc i) jprev)]))
(: nat* : Nat Nat -> Nat)
(define (nat* i j) (match* (i j)
[('Zero _) 'Zero]
[(_ 'Zero) 'Zero]
[((Suc _) (Suc jprev)) (nat+ i (nat* i jprev))]))
```

And in Haskell:

```
nat_add :: Nat -> Nat -> Nat
nat_add n1 Zero = n1
nat_add Zero n2 = n2
nat_add n1 (Suc n2) = Suc (nat_add n1 n2)
nat_prod :: Nat -> Nat -> Nat
nat_prod _ Zero = Zero
nat_prod Zero _ = Zero
nat_prod n1 (Suc n2) = nat_add n1 (nat_prod n1 n2)
```

Again, my Racket code translates easily to Haskell. I’m again struck by how much easier to read the Haskell code is. I haven’t
yet had to indent *anything*, which is impressive. I just hope that the whole
spaces-as-function-application thing doesn’t become ambiguous down the line,
but I feel like it will.

## Parting notes

Is it too much to ask for either of these languages to have a *normal* comment
string? Racket’s `;`

I kinda got used to, but it’s still clunky. There’s also no
way to block-comment, which is a bit annoying, but not too bad with
vim-commentary. But Haskell, why? Oh
god, why? `--`

is just so unreadable. Good thing I have vim set to italicize and dim the colors on all comments,
or I’d gloss right over them. And the block comments too…

Okay, /rant. For now, the conclusion is this: if you’re coming from really any Lisp dialect and you want to learn Haskell, go for it. The syntax is bound to be weird, but you’ll get used to it, and everything should be on conceptually familiar ground, at least to start. Also, Learn You A Haskell is great.

Alright, I guess that’s it for season 1! Roll credits! Season 1, boom!

### Correction: 07 February 2017

My friend Isha informed me that Racket does in fact
have block comments with `#| ... |#`

. However, I don’t think that detracts from
my point of both languages having terrible comment strings.