Hacker News new | ask | show | jobs
by mlazos 2131 days ago
This is a great post, I’ve seen a lot of those patterns before and it’s nice to have them in one place! One criticism I have though is I’m not sure about the advantage of phantom types, it seems like boilerplate to me. I feel like generalized algebraic data types are a strictly better pattern to follow to solve the issue of restricting type variable bindings to specific types.
3 comments

I introduced phantom types to a codebase recently, although it was Scala rather than Haskell. The code was using arrays of bytes, where:

- Some contain plaintext, some contain ciphertext

- Some contain keys, some contain data

- The keys themselves exist in plaintext and ciphertext forms (data keys generated by AWS KMS)

- Some keys were used for signing/verifying, some were used for encrypting/decrypting

- Some arrays contain Base64 data (for embedding in JSON), some contain unencoded data

Using 'Array[Byte]' would work, but would be error-prone. Using distinct types or wrappers like 'Base64[Plaintext[Key[Signing]]]' would require lots of extra definitions, and wrapping/unwrapping scattered around the code. Phantom types let me use type signatures with the right amount of specificity and polymorphism as needed, whilst the code itself was the 'straightforward' version without wrapping/unwrapping.

> I feel like generalized algebraic data types are a strictly better pattern to follow to solve the issue of restricting type variable bindings to specific types.

GADTs which don't store a value based on one of their type parameters are still making use of phantom types. The key concept with a GADT is that you can have type variable binding(s) (whether phantom or concrete) which are determined by the constructor. If you aren't taking advantage of that then you're probably just defining an ordinary data type using GADT syntax.

Phantom types can be useful when modelling currency: the "implementation" stays the same but you want to avoid summing two different currencies by mistake.

https://ren.zone/articles/safe-money