Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/parsonsmatt/record-wrangler
Alter datatypes at your leisure!
https://github.com/parsonsmatt/record-wrangler
Last synced: 13 days ago
JSON representation
Alter datatypes at your leisure!
- Host: GitHub
- URL: https://github.com/parsonsmatt/record-wrangler
- Owner: parsonsmatt
- License: apache-2.0
- Created: 2019-04-01T19:02:19.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2022-08-05T19:10:27.000Z (over 2 years ago)
- Last Synced: 2024-10-04T18:14:41.205Z (about 1 month ago)
- Language: Haskell
- Size: 18.6 KB
- Stars: 8
- Watchers: 10
- Forks: 0
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
- Changelog: ChangeLog.md
- License: LICENSE
Awesome Lists containing this project
README
# record-wrangler
[![Build Status](https://travis-ci.org/lumihq/record-wrangler.svg?branch=master)](https://travis-ci.org/lumihq/record-wrangler)
This package uses `TemplateHaskell` to alter records in ways that may be convenient for you.
## Inspiration
Let's say you've got a set of API types and a set of domain types.
The API types define your HTTP contract, and you generically derive ToJSON and FromJSON instances from their field labels.
They look like this:```haskell
data User = User
{ id :: Int
, name :: String
, age :: Int
}data Dog = Dog
{ id :: Int
, name :: String
, toy :: FavoriteToy
, ownerId :: Int
}
```The domain types for your business logic look a little different, though.
The record fields are prefixed with an `_` underscore character, to allow for `lens` derivation.
We can pretend they have other differences that are relevant to internal details and irrelevant for showing off `record-wrangler` if that makes you feel better.```haskell
data Dog = Dog
{ _id :: Int
, _name :: String
, _toy :: FavoriteToy
, _ownerId :: Int
}makeLenses ''Dog
data User = User
{ _id :: Int
, _name :: String
, _age :: Int
}makeLenses ''User
```If the record fields were the same, then we could just write the conversion function using `RecordWildCards` and it'd be fine:
```haskell
convertUser Api.User{..} = Domain.User{..}
```However, because the field labels are different, we have to do it manually:
```haskell
convertUser Api.User{..} = Domain.User
{ _id = id
, _name = name
, _age = age
}
```This is annoying and boilerplatey.
I don't know about you, but I hate writing code, for every line of code I write is a chance to mess up.
Let's use `record-wrangler` to make these conversions easier.```haskell
wrangle ''Api.User defWrangleOpts
{ fieldLabelModifier = \fieldStr -> '_' : fieldStr
}
```This is going to take the `Api.User` type and modify it slightly.
By default, we append a `'` to the constructor name, type name, and field labels.
Here, we've decided to prepend a `_` character to the field label.
It also generates a function `wrangleUserToUser'` which converts the old record to the modified one.With the power of view patterns, our conversion function is now quite concise:
```haskell
convertUser :: Api.User -> Domain.User
convertUser (wrangleUserToUser' -> User'{..}) = Domain.User{..}
```