Tools:

My setup matches my personality and that is I always go for the bare minimum. I download all these tools using nixpkgs and I enable haskell-mode in doom-emacs. That’s it! I start writing Haskell.

Once I start writing Haskell I have another terminal open that runs ghcid. It has very fast development feedback loop, it’s how I know if my types are matching. I use typed-holes heavily so ghcid can tell me what types I need for a section of my code.

Here’s a contrived example

```
add :: Integer -> Integer -> Integer
= x `_whatdo` y add x y
```

This will be ghcid’s response in the repl

```
<interactive>:3:13: error:
• Found hole: _what :: Integer -> Integer -> Integer
Or perhaps ‘_what’ is mis-spelled, or not in scope
• In the expression: _what
In the expression: x `_what` y
In an equation for ‘add’: add x y = x `_what` y
• Relevant bindings include
y :: Integer (bound at <interactive>:3:7)
x :: Integer (bound at <interactive>:3:5)
add :: Integer -> Integer -> Integer (bound at <interactive>:3:1)
Valid hole fits include
add :: Integer -> Integer -> Integer (bound at <interactive>:3:1)
seq :: forall a b. a -> b -> b
with seq @Integer @Integer
(imported from ‘Prelude’
(and originally defined in ‘ghc-prim-0.5.3:GHC.Prim’))
(-) :: forall a. Num a => a -> a -> a
with (-) @Integer
(imported from ‘Prelude’ (and originally defined in ‘GHC.Num’))
asTypeOf :: forall a. a -> a -> a
with asTypeOf @Integer
(imported from ‘Prelude’ (and originally defined in ‘GHC.Base’))
const :: forall a b. a -> b -> a
with const @Integer @Integer
(imported from ‘Prelude’ (and originally defined in ‘GHC.Base’))
max :: forall a. Ord a => a -> a -> a
with max @Integer
(imported from ‘Prelude’
(and originally defined in ‘ghc-prim-0.5.3:GHC.Classes’))
(Some hole fits suppressed; use -fmax-valid-hole-fits=N or -fno-max-valid-hole-fits)
```

This tells me that I need a function that takes two `Integer`

that also outputs an `Integer`

. This even tells me the “Relevant bindings” and “Valid hole fits” which is amazing. ghcid helps as much as it can. This flow goes a very long way. It starts getting hazy for me when it comes to lens errors, but I’m sure if I use lens more often I’ll be able to decipher what ghcid is telling me much quickly. This even works in the type level.

```
add :: _whatdo
= x + y add x y
```

ghcid repl will respond with

```
<interactive>:8:1: error:
• Couldn't match expected type ‘_whatdo’
with actual type ‘Integer -> Integer -> Integer’
‘_whatdo’ is a rigid type variable bound by
the type signature for:
add :: forall _whatdo. _whatdo
at <interactive>:7:1-14
• The equation(s) for ‘add’ have two arguments,
but its type ‘_whatdo’ has none
• Relevant bindings include
add :: _whatdo (bound at <interactive>:8:1)
```

ghcid is the reason I don’t use any IDE or any fancy editor plugins. I only have syntax highlighting and some formatting in my emacs.

When it comes to actually running my code I usually use cabal. After ghcid tells me my code is clear I run

```
cabal new-build
cabal new-run
```

Sometimes I use stack because of yesod. That’s mostly for work.

I’m aware of the holy war between stack, cabal, and nix, I hope this blog doesn’t get involved in that war. I use all of them. They all have a spot in my workflow.