-
Notifications
You must be signed in to change notification settings - Fork 25
Description
Hi,
I was trying to use a simple high-order function but I am not sure I got this correctly. The original function is here:
fun filter[a](fn : a -> bool, ps : Par[a]) : Par[a]
join(ps >> fun (item : a) => if fn(item) then
liftv(item)
else
empty[a]()
end)
endHowever, I need to work with linear a;I have added the linear a type variable to the function and I also also use a borrow block in the internal function to be able to alias the linear item; after the borrow block I expected to get back my normal linear item:
fun filterL[linear a](fn : a -> bool, ps : Par[a]) : Par[a]
joinL(ps >> fun (item : a)
var b = false
borrow item as borrowItem in
if fn(borrowItem) then
b = true
end
end
if b then
liftvL(item)
else
emptyL[a]()
end
end)
endHowever, this throws the typing error:
"ParT.enc" (line 69, column 22)
Type 'borrowed linear a' does not match expected type 'linear a'
In expression:
fn(borrowItem)
Since it does not allow me to use the function fn without adding the borrowed annotation, an internal detail in the implementation pollutes the top level signature of the function. The end result is:
fun filterL[linear a](fn : borrowed a -> bool, ps : Par[a]) : Par[a]
joinL(ps >> fun (item : a)
var b = false
borrow item as borrowItem in
if fn(borrowItem) then
b = true
end
end
if b then
liftvL(item)
else
emptyL[a]()
end
end)
endThis however does not compile because the type parameter a in ps >> fun (item : a) now needs to have the borrowed annotation as well. Ok, so I update the code to (addition of borrowed in the lambda function):
fun filterL[linear a](fn : borrowed a -> bool, ps : Par[a]) : Par[a]
joinL(ps >> fun (item : borrowed a)
if fn(item) then
liftvL(item)
else
emptyL[a]()
end
end)
endNow, it complains that liftvL:
"ParT.enc" (line 68, column 19)
Type 'borrowed linear a' does not match expected type 'linear a'
I do understand the message but at this pace, a combinator that wants to work with read and linear modes needs to implement at least three functions:
- one function that takes a linear thing
- one function that takes a linear borrowed thing
- one function that uses the
sharableannotation forread
My questions given the reasoning above are:
- Is there anything that I can do to the simple
filtercombinator that would give me the semantics that I want? - If not, is there anything that we can do to improve re-using code without having to write at least three functions?
- At another level, I do understand that a function that is given a linear argument that has been borrowed has the
linear borrowedannotation. However, for functions, isn't this exposing and tying the internal implementation details to top level types? - Can we do some kind of static analysis whenever we have a high-order function that receives a linear type so that it checks if it is possible to use the borrowed thing without having to "creep" the internal implementation to the top level types in the high-order function?