Add toLinearN; narrow the coercion scope#346
Conversation
|
Should we make at least some of these functions more polymorphic? I would think something like toLinear
:: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep)
(a :: TYPE r1) (b :: TYPE r2) p m x.
(a %p-> b) %m-> (a %x-> b)
toLinear2
:: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep) (r3 :: RuntimeRep)
(a :: TYPE r1) (b :: TYPE r2) (c :: TYPE r3) p q m x y.
(a %p-> b %q-> c) %m-> (a %x-> b %y-> c)
toLinear3
:: forall (r1 :: RuntimeRep) (r2 :: RuntimeRep)
(r3 :: RuntimeRep) (r4 :: RuntimeRep)
(a :: TYPE r1) (b :: TYPE r2) (c :: TYPE r3) (d :: TYPE r4) p q r m x y z.
(a %p-> b %q-> c %r-> d) %m-> (a %x-> b %y-> c %z-> d)This doesn't do much for |
|
Since |
|
Might we want a version that takes a full list of multiplicity changes? Something like this? toLinearList @'[ 'One :=> 'Many, _ :=> 'One, 'Many :=> n] ... |
ae770f5 to
b0bf1a4
Compare
aspiwack
left a comment
There was a problem hiding this comment.
I have a bunch of questions below. But I'm favourable to the change as a whole. As well as making the toLinearX functions returning functions of an arbitrary multiplicity (though maybe their name isn't ideal anymore, but it's not too serious).
I've got to admit, I'm feeling a bit of a mix of amazement and dismay that the Unsafe module is seeing such love 🙂 .
src/Unsafe/Linear.hs
Outdated
| -- | The actual implementation of 'ToLinearN', using the inductive natural | ||
| -- number it's handed. | ||
| type ToLinearN' :: forall {rep :: RuntimeRep}. INat -> TYPE rep -> TYPE rep -> Constraint | ||
| class ToLinearN' arrs f g where | ||
| prf :: UnsafeEquality f g | ||
| instance ToLinearN' k fb gb => ToLinearN' ('S k) ((a :: TYPE repa) %p-> (fb :: TYPE repb)) (a %q-> (gb :: TYPE repb)) where | ||
| prf = case prf @k @fb @gb of | ||
| UnsafeRefl -> case unsafeEqualityProof @p @q of | ||
| UnsafeRefl -> UnsafeRefl | ||
| instance ToLinearN' 'Z (a :: TYPE rep) (a :: TYPE rep) where | ||
| prf = UnsafeRefl |
There was a problem hiding this comment.
Does this produce an O(n) irreducible proof? I'm not super up to date with the new unsafeEqualityProof mechanism.
And if so: is it bad?
There was a problem hiding this comment.
The proof can get a bit long, but I don't think that we can do anything about it. It'll be erased in Core Prep or so.
src/Unsafe/Linear.hs
Outdated
| -- | @ToLinearL l f g@ means that @f@ and @g@ are the same with the | ||
| -- possible exception of the multiplicities of some of the first arrows, | ||
| -- as described by the list @l@. | ||
| type ToLinearL :: forall {rep :: RuntimeRep}. [Change] -> TYPE rep -> TYPE rep -> Constraint | ||
| class ToLinearL l f g where | ||
| -- | @unsafeLinearityProofL \@l \@f \@g @ is a fake proof that @f@ and @g@ are | ||
| -- the same with the possible exception of the multiplicities of the first | ||
| -- arrows given by the list @l@. | ||
| unsafeLinearityProofL :: UnsafeEquality f g | ||
| instance ( ToLinearN' ni f g, UnifyL ni f g, UnifyL ni g f | ||
| , ni ~ Length l, UseChanges l f g) => ToLinearL l f g where | ||
| unsafeLinearityProofL = prf @ni |
There was a problem hiding this comment.
Is this really necessary? This can be achieved with a ToLinearN and a type annotation. I think that I'm essentially questioning the need for exporting an operator from this Unsafe module.
There was a problem hiding this comment.
Yeah, you're right. Type application with plenty of underscores should be just as good.
Make `toLinear`, etc., explicitly coerce only *multiplicities*, rather than whole arrow types. This is just a cleanup; it shouldn't have any practical impact.
0871ef8 to
466ace3
Compare
|
@aspiwack, I implemented your suggestions. Your suggested approach to |
|
Commits are now squashed to logical units. |
9c88b2d to
3128aff
Compare
1703838 to
812286f
Compare
aspiwack
left a comment
There was a problem hiding this comment.
Let's address the small comment below, then when you are happy, I'll merge.
|
I think this is ready to merge. |
|
Oh, I guess I should remove the word TODO... |
Use the class system and some type-level hacking to generalize @toLinear@, @toLinear2@, and @toLinear3@.
This is mostly useful for `toLinear2` and `toLinear3`, where we may want to make *some* of the arrows linear but leave others as they are.
|
OK, now it's really done. |
aspiwack
left a comment
There was a problem hiding this comment.
Fantastic. Thanks a lot!
CI is green, which does mean that generalising the types of the unsafe operations hasn't been a problem in practice.
Let me merge now.
@utdemir it would be interesting to see if this PR has any effect on your benchmarks (I don't expect so, but you never know).
Make
toLinear, etc., explicitly coerce only multiplicities,rather than whole arrow types. This is just a cleanup; it shouldn't
have any practical impact.
Add
toLinearNandtoLinearLto generalizetoLinear,toLinear2, andtoLinear3.