I've been experimenting with linear types recently, and have been wondering if the following transformation is possible. It's definitely not valid without linear types.
The aim is to lower the higher order function argument. This should be ok, because linear types ensure the HOF is called exactly once, so exactly 1 value of a
exists. The issue is how to escape the lambda and observe a
lower :: ((a %1-> b) %1-> r) %1-> b %1-> (r,a)
Edit: You cannot safely implement
lower
. As dfeuer and danidiaz say in comments: what if the first argument to lower is the identity function? With the implementation I showed in my old answer below you can write:Which will produce an error at run time:
So linear types do not give enough guarantees to make it safe to implement this function.
Edit2: You can save the situation by slightly changing the signature to:
lower :: ((a %1 -> b) %1 -> Ur r) %1 -> b %1 -> (Ur r, a)
. This way it is impossible to store the linear argumenta %1 -> b
inr
.Old answer
This may not be the answer you are looking for, but if you know for sure that it is safe, then you can bend the rules a bit:
I think the main purpose of linear types is only to get the extra type-level information, so I don't think there are any safe primitives that let you do this more cleanly (although I don't know all the ins and outs). Linear types do allow you to implement a safe interface with unsafe operations underneath. See for example how many times
toLinear
is used in this file from linear-base.Perhaps the unsafe bits above can be outsourced to a lower-level library. Maybe something like promises, but then with linear types.