PureScript pitfalls wiki

This post is a wiki! Any user can edit it to contribute!
Add items to this wiki post which you think are common pitfalls people stumble on when using PureScript for the first time or when using unfamiliar features of the language. Hopefully this is a good resource to use when making a “more professional or vetted” list of pitfalls.

Type synonyms

Recursive type synonyms

You can’t define recursive type synonyms that never terminate; this will blow up in the compiler. If you need a type that refers to itself, then you should reach for a newtype or data constructor instead.

forall in type synonyms

You usually do not want a forall in a type synonym unless you are working with rank-N types. This is pretty uncommon in a usual application; if you aren’t specifically looking for that, then a forall in a type synonym is probably not what you want.

A brief example, with code Let's say you want to represent an address book as some container, `f` (which has a `Alternative` instance), containing a collection of `Contact`. A first cut at an `AddressBook` type might look like this:
type AddressBook = forall f. Alternative f => f Contact

myFunc :: Contact -> AddressBook -> AddressBook

The idea is that you can insert a contact into a collection and produce a new collection. But this type will not give you what you want. Type synonyms can be inserted as-is where they are used:

-- this has a very different meaning
myFunc :: Contact -> (forall f. Alternative f => f Contact) -> (forall f. Alternative f => f Contact)

-- from this, which is what we wanted
myFunc :: forall f. Alternative f => Contact -> f Contact -> f Contact

What we should have written was the below type, with the constraints placed on the function where the forall is declared, not in the type synonym.

type AddressBook f = f Contact