Code available on GitHub, package available on Hackage.IntroductionIn Haskell, we usually model data using algebraic data types, like this:1 data Maybe a = Nothing | Just a Here we defined a Maybe type, which has two constructors, Nothing and Just. The Just constructor has one argument, while Nothing as none.It is common to consider these constructors’ arguments as fields, which can be mainly distinguished by their position in the constructor’s declaration. When data types have many fields, it becomes a bit of a pain to select them, for example, in functions like these:1 2 3 4 5 6 7 8 9 10 data URL = URL String -- ^ Scheme String -- ^ Hostname Maybe Int -- ^ Port String -- ^ Path [(String, String)] -- ^ Query Parameters Maybe String -- ^ Fragment (#) getPath :: URL -> String getPath (URL _ _ _ path _ _) = path Thankfully, in GHC 7.4.1 was introduced the record syntax, which allows naming fields, like this:1 2 3 4 5 6 7 8 data URL = URL { scheme :: String, hostname :: String, port :: Maybe Int, path :: String, queryParams :: [(String, String)], fragment :: Maybe String, } This lets us write the getPath function much more concisely.1 2 getPath :: URL -> String getPath = path Unfortunately, since Haskell’s type system is primarily nominal (=/= structural), we cannot set constraints that asks records to have a given set of fields. Yes, there is a HasField typeclass, but it is too verbose for my liking, and only allows selecting a field, not updating it:1 2 getName :: (HasField "name" a String) => a -> String getName elem = getField @"name" elem Lenses do provide getters and setters, but not in a name-polymorphic way, like HasField. Alternatively, it is common to use heterogeneous lists to build records and work around the type system to simulate structural subtyping. However, we will see in the microbenchmark section why using these lists is not optimal.Let’s consider another strongly typed language, TypeScript, which does support structural subtyping. It also provides ...
First seen: 2025-08-20 06:05
Last seen: 2025-08-20 13:16