Created
January 2, 2021 18:55
-
-
Save schicks/5542f949e7af63ca66e5c167e8d1e294 to your computer and use it in GitHub Desktop.
Koka for loops
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
effect leq<a> { | |
fun leq(first: a, second: a) : bool | |
} | |
fun for( | |
from: a, | |
incr: a -> <div,leq<a>|e> a, | |
to: a, | |
do: () -> <div,leq<a>|e> () | |
) : <div,leq<a>|e> () { | |
if (from.leq(to)) then { | |
do(); | |
for(from.incr, incr, to, do) | |
} else () | |
} | |
fun using-for () { | |
var something := 0 | |
with fun leq(first: int, second: int) {first <= something} | |
for(0, fn (a) {a+1}, 10) { | |
something := something + 1 | |
} | |
var something-else := "a" | |
with fun leq(first: string, second: string) {first <= second} | |
for("", fn (a) {a+"a"}, "aaaaaaa") { | |
something-else := something-else + "a" | |
} | |
(something, something-else) | |
} |
But don't you need a generic function parameter for each "type class" you're handling? Or is there a way that your one generic function argument can be row typed?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Effects with type parameters are no different than generic parameters as being
stack generic
or whatever the term might be. One major difference with implicits is that the compiler automatically applies as much as it can at the place most close to the function that needs it. So if you want to show alist<(a,a)>
you don't need to "drill" down the implementation of show for lists or tuples, just for the generic typea
. Also, at the place you call the function, ifa
is instantiated to something non-generic the compiler automatically supplies the correct show function as long as it is unambiguous. In other words, you trade adding a generic effect on the return type for adding a generic function in the parameter list, and you don't have to provide a handler in the dynamic scope. You also get more clear lexically scoped passing of the implementation, instead of an implicit dynamically scoped implementation, which could unexpectedly be overridden by a user function passed in.