Skip to content

Instantly share code, notes, and snippets.

@Gabriella439
Last active April 12, 2020 13:20
Show Gist options
  • Save Gabriella439/563fa662f84e0a845c79775756cfce78 to your computer and use it in GitHub Desktop.
Save Gabriella439/563fa662f84e0a845c79775756cfce78 to your computer and use it in GitHub Desktop.
API design notes
* Importance of category theory
* Answers the question: "What is a *timeless* API?"
* What does "timeless" mean?
* Likely to still be relevant years from now
* Likely to be low maintenance (since unlikely to change)
* Less likely to be subject to controversy or discussion ("obvious")
* Examples:
* Everything Haskell's typeclassopedia (except maybe `Foldable`)
* Categories / Monoids
* `(.)` / `id`
* `<=<` / `return`
* `&&` / `True`
* `||` / `False`
* `+` / `0`
* `*` / `1`
* Functors / Monoid Homomorphisms
* `fmap` (obviously)
* `length`
* `filter`
* `lift`
* I've actually done the experiment, authoring packages both based on
category and not based on category theory and difference in
maintainability is quite stark
* GIVE MODULES SHORT NAMES
* Please get rid of the `Data` / `Control` prefix
* A good rule of thumb is to name the default module to import after your
package (with no extra cruft)
* If you're going to claim valuable package namespace, then there's no
harm claiming valuable module namespace either
* This rule of thumb also greatly reduces the likelihood of module
naming conflicts between packages
* For example, the default import for the `lens` package should really be
just `Lens` (no `Control.` prefix)
* How deal with types with default values
* Just expose the record type. Stop obsessing over perfect backwards
compatibility
* At most, provide a `defaultFoo` value that users can use to minimize
migration work
* Haskell is a typed language. Your users will be easily able to update
their code if you change the shape.
* Think through what import lists will be like for your users
* "The idiomatic Haskell program is 6 language extensions, 20 imports, and
1 line of Perl"
* Re-export everything your users need in some module
* Professional users might not use it, but helps for beginners or
tutorial material
* Tell your users how to import your modules qualified
* Preferably by example (that you included in your haddocks)
* Even better if your module name is short enough that fully qualified is
fine (e.g. `Turtle`, `Pipes`)
* Users hate lots of type parameters
* Ask me how I know
* This seems to be type safety tradeoff that most users are not willing to
make
* Avoid type synonyms
* Prefer newtypes or no synonym at all
* Type synonyms don't reliably show up in inferred types or error messages
* Also introduces more indirection than most users are comfortable with
* Which string types to use?
* Prefer strict `Text` / `ByteString` over their lazy alternatives
* Avoid `String`
* Avoid typeclass dependency hell
* If you introduce a new typeclass, please do not introduce instances for
types other than types within the same package or ones in `base`
* Don't make the mistake the `semigroups` package made where it depended on
way too many packages just to provide instances.
* `deriving (Generic, Foo)` is pretty close to the best thing ever
* Please implement a way to derive your typeclass if you introduce one
* Think through what language extensions are necessary to use your package
* Provide named versions of operators
* Some users prefer to qualify essentially everything and they'd prefer
to qualify named things rather than operators
* Operators also require your users to learn fixity and precedence
* Better to leave things out if you're not sure
* It's way easier to add things later and an excellent opportunity for
new contributors to "cut their teeth"
* Minimize "unchecked" `IO` exceptions
* i.e. `throwIO`
* Really hard to refactor weakly-typed exception hierarchies later on
* Minimize use of `FlexibleContexts` / `FlexibleInstances`
* Refactoring your type classes to avoid these instances is worth it!
* Deciding on the right balance of type safety versus convenience
* In Haskell the typical level of safety to aim for is to make bugs hard to
introduce unintentionally, not impossible
* Take requests from the audience to review specific packages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment