agrafix / superrecord

Haskell: Supercharged anonymous records
BSD 3-Clause "New" or "Revised" License
83 stars 16 forks source link

Add inject/project functions + minor adjustments #31

Closed sheaf closed 3 years ago

sheaf commented 3 years ago

Changes in this PR:

(1) Generalise the record construction functions to allow an applicative functor, i.e. we go from

  build :: (forall (l :: Symbol) a. (KnownSymbol l, c l a) => FldProxy l -> Proxy# a -> a) -> Rec lts

to

build :: Applicative f => (forall (l :: Symbol) a. (KnownSymbol l, c l a) => FldProxy l -> Proxy# a -> f a) -> f (Rec lts)

The old behaviour is recovered by taking f ~ Identity, which is what the new pure builder function does.

(2) RecTy now returns a Maybe Type, which means on top of computing the presence of a key it can also compute the absence of a key (as opposed to being stuck). This was needed for (4). I also removed the excessive polymorphism in the return kind of RecTy, as it can only ever return types because of the definition of :=, and the extra polymormphism could potentially cause issues with ambiguous kind variables. (3) Export the helper typeclass TraversalCHelper. This is somewhat unfortunate as I thought user code would not need it, but as it currently stands you can run into situations which require it. (4) Add functions to project a record onto a record with a subset of the fields, and to inject some fields into a record (the inject function – see its documentation for more info, but it's like smash from generic-lens, except with a slightly more lenient type as it doesn't require a strict subtyping relationship). (5) Add a utility type family Intersect for computing the intersection of two sets of record fields. This is useful in tandem with (4), e.g. to project out a set of components common to two records.

agrafix commented 3 years ago

Nice! Would you be open to add some tests to the test-suite for the two new functions as well?

sheaf commented 3 years ago

I added some tests for all the functions I added so far, let me know what you think. If you have suggestions for better names for the utility typeclasses (ConstC, Tuple22C etc), please let me know. I think eventually we might want to split this up into a separate library for manipulating constraints.

agrafix commented 3 years ago

Thanks, this is great. I'll merge as is. For the utility type classes, I'm not sure how much better names would help. However, maybe we could add some doc strings?