Overview A simple expression language More precise types with GADTs More flexible types with GADTs Encoding GADTs in Rust Type equality witnesses Trait constraint witnesses Using specialisation to recover constraints Why this works Limitations Conclusion Rust doesn’t have GADTs (generalised algebraic data types), but we can get surprisingly close with some creative type-level tricks. This post…
Overview Background Examples Differences Labels Changes in generic-lens Conclusion I’m happy to announce a new library, generic-optics , accompanied by version 2.0.0.0 of generic-lens . Background A few months ago, the folks at Well-Typed announced the optics library , which aims to improve on the user experience compared to the lens library. Oleg Grenrus has written an excellent migration guide…
Overview Constraints newtypes (kind of) A real world example Acknowledgements The list of type class constraints in a function signature can sometimes get out of hand. In these situations, we can introduce a type synonym (thanks to ConstraintKinds ) to avoid repetition. Say we want to group together the Show and Read constraints: type Serialise a = ( Show a , Read a ) Now Serialise a can be used…
One of the main selling points of Haskell is that despite (or because) of its strong static type system, it frees us from the burden of having to spell out tedious type signatures everywhere. Type inference is a blessing, but sometimes it can also be a curse. Inference too good can hinder the readability of code, because the compiler knows what the type of an identifier is even when we don’t. It’s…
The aim of this series of blog posts is to shed light on some of the darker corners of the vim text editor that I have encountered over the years. Each post will focus on one particular feature, and should take no longer than a couple of minutes to read. Today, I’d like to talk about the <C-a> key sequence (that is, control+a). It is extremely simple: pressing <C-a> searches the current line…
Overview Under the hood Barewords Implicit parameters (enabled with the {-# LANGUAGE ImplicitParams #-} pragma) provide a way to dynamically bind variables in Haskell. For example, the following function can be called in any context where ?x is bound: foo :: ( ? x :: Int ) => Int foo = ? x bar :: Int bar = let ? x = 10 in foo Unlike type classes, implicit parameters are bound locally. But what if…
Overview Type family evaluation semantics Custom type errors Conclusion Custom type errors are a great way to improve the usability of Haskell libraries that utilise some of the more recent language extensions. Yet anyone who has written or used one of these libraries will know that despite the authors’ best efforts, there are still many occasions where a wall of text jumps out, leaving us puzzled…
Overview Motivation Primitives AppendSymbol CmpSymbol Decomposition Head Uncons Conclusion Haskell, as implemented in GHC, has a very rich language for expressing computations in types. Thanks to the DataKinds extension, any inductively defined data type can be used not only at the term level, but also at the type level. A notable exception are strings, which provide the main theme for today’s…
Overview The problem The solution The boring instances Incoherent instances Default signatures A few more instances Conclusion Acknowledgements Recently, I’ve been experimenting with deriving various type class instances generically, and seeing how far we can go before having to resort to TemplateHaskell. This post is a showcase of one such experiment: deriving Bifunctor , a type class that ranges…
Overview Overview Examples field typed position super (row polymorphism) _Ctor mtl Performance Quick note (migration) Acknowledgements The generic-lens library provides utilities for deriving various optics for your datatypes, using GHC.Generics . In this post I’ll go over some of the features and provide examples of using them. Overview Lenses have proven to be an exteremely powerful tool in the…
Overview The problem Type-level parsing How the sausage gets made: computing the output type Conclusion One of the classic examples that keeps coming up when talking about dependently typed programming languages is the “safe” printf function – one that ensures that the number and type of arguments match the requirement in the format specification. In languages like Idris, this is just a function…
Overview How? The repMax problem Wait, what? States travelling back in time What are states anyway? Finally, the time machine, TARDIS A single-pass assembler: an example IO doesn’t mix with the future! (The past is fine) Thanks Browsing Hackage the other day, I came across the Tardis Monad . Reading its description, it turns out that the Tardis monad is capable of sending state back in time. Yep.…