Row polymorphism packages in Haskell

In my experience, row polymorphism significantly reduces boilerplate when writing business applications. I used to rely on the row-types package whenever I needed row polymorphism. The package was once used at Target but appears to have been abandoned, with the author moving it to their personal account.

Although there’s a GHC proposal for native support, it seems to have stalled. In the meantime, I’m curious about which packages the community uses in commercial apps.

4 Likes

I don’t use it, but large-anon: Scalable anonymous records is most likely best because of its scalability.

1 Like

There is an elaborate wiki page on GHC’s gitlab here: extensible records · Wiki · Glasgow Haskell Compiler / GHC · GitLab, and also the libraries vinyl, HList and record. Don’t know about their usability though.

1 Like

Thank you, @arybczak and @markus. I’ve looked into large-anon and vinyl previously. I’m more interested in hearing about any production experiences with these or other alternative packages.

I’m using large-anon sporadically in a newish production codebase. Nothing super compelling yet. It’s straightforward to use and has neat syntax. I’ve used it for some toJSON instances where instead of importing Data.Aeson's object and .= (the latter especially is being a name that clashes with many libs including lens/optics) you can just use record syntax. Like

instance ToJSON MyError where
  toJSON (MyError (FailureResponse req resp)) = toJSON ANON
    { request = ANON
      { httpVersion = Text.decodeUtf8Lenient req.requestHttpVersion
      , method = Text.decodeUtf8Lenient req.requestMethod
      , path = Text.decodeUtf8Lenient req.requestPath
      }
    , response = ...
    }

But I think where it would be a much more tangible benefit is if SQL libraries like beam/opaleye/hasql-th adopted it for return and parameter types. It’s fairly cumbersome defining new types for every new query, or using tuples. Squeal-postgresql has a lot of integration with generics-sop which is nice but when I used it last had a pretty big compilation time penalty.

3 Likes

FYI Opaleye doesn’t require any specific structure of product types in its API. You can use anything you like (including large-anon presumably) as long as you can write the correct instance.