Closed nfrisby closed 5 years ago
I came up with a simpler idea on pen and paper. Just use the function's graph as a frag.
infix 7 :=
data Mapping dom cod = To dom cod
type (:=) = To
type family DomFrag (fr :: Frag (Mapping dom cod)) :: Frag dom where {}
The key ingredient is a special rule in envMultiplicity
: if all multiplicities in p
are non-negative, then the multiplicity of k := v
in p
is at most the multiplicity of k
in DomFrag p
.
I'm trying this now.
I pushed branch issue/19-domfrag
. It has a first attempt at Record
, using DomFrag.
It went according to the pen and paper plan, except for the type of Data.Motley.Row.ret
(and thereby prj
and rmv
).
Without FragEQ (lbl := a) p ~ 'Nil
, we are attempting the following.
have:
FragEQ lbl (DomFrag p) ~ 'Nil
SetFrag (DomFrag (p :+ lbl := a)) ~ '()
SetFrag (p :+ lbl := a) ~ '()
want:
FragEQ (lbl := a) p ~ 'Nil
which simplifies to
have:
FragEQ lbl (DomFrag p) ~ 'Nil
SetFrag (DomFrag p)
SetFrag (FragNE (lbl := a) p)
SetFrag (FragEQ (lbl := a) p :+ '()) -1 <= p(lbl := a) <= 0
want:
FragEQ (lbl := a) p ~ 'Nil
That doesn't currently work. I think it's because the current implementation is conservative because p
could for example be
'Nil :+ lbl := b :- lbl := a
for some b /~ a
.
I need to go back to pen and paper to determine if that is overly conservative, and how to update the constraint simplifier to be less conservative. If it's not overly conservative, then maybe DomFrag
is the wrong approach. Perhaps a FragNEArg lbl p ~ p
instead... seems heavier though.
Edit: I'm now thinking FragEQ (k := v) p ~ 'Nil
might actually be the correct constraint for functions that remove a field from a row. Note that ext
uses FragEQ k (DomFrag p) ~ 'Nil
. I wasn't expecting an asymmetry, but maybe it's just unexpected, not wrong. I think I need to try using the interface for some actual work before I'll be able to tell.
Edit 2: I think DomFrag
suffices for a quite a bit, but it is ultimately incomplete compared to FragEQArg, FragNEArg :: dom -> Frag (Mapping dom cod) -> Frag (Mapping dom cod)
: counting doesn't cut it. Then FunFrag (p :+ k := a) = (FunFrag (FragNEArg k p),FragEQArg k p ~ 'Nil)
. I need to come up with example programs.
I merged the function graph approach using only Frag
constraints plus DomFrag
into develop
at commit 94dd754. Closing.
What will it take to associate a type with each frag element?
This is already possible to a limited degree, right now. If the label alone determines the type and you know them all, then you can use a data/type family as/within the functor argument to
Prod
andSum
. But that's a disappointing limitation -- we want extensibility and anonymity here too.I'm hoping the answer isn't just "duplicate all the frag machinery but on type-level pairs and unify the second part whenever the first part matches". Even in that case, does the
SetFrag
constraint prevent any ambiguity regarding interleavings of insertions/deletions, or will that require additional care?Two ideas:
Another special data kind. This one is not a group. It would require #5: frags in kinds.
Note that we don't even need
'Emp :: Row 'Nil cod
, let aloneRem k p
. But it might be nicer to have them anyway. The basic idea is to letFrag
handle all the interesting constraints, so that the frag-index onRow
drives its shape via eta-reduction.