Skip to content

Instantly share code, notes, and snippets.

@arsdragonfly
Last active August 2, 2021 13:21
Show Gist options
  • Select an option

  • Save arsdragonfly/de89bc8e70b6f05a8e193ea183c6e4f2 to your computer and use it in GitHub Desktop.

Select an option

Save arsdragonfly/de89bc8e70b6f05a8e193ea183c6e4f2 to your computer and use it in GitHub Desktop.
Algebraic Interrupts (Effects) using Koka
import std/num/random
effect control eat-icecream() : ()
effect control check-cost() : int // returns the cost in int
fun my-eat-icecream() {
eat-icecream();
val cost = check-cost();
if (cost > 2)
{
return cost
}
else {
eat-icecream();
return check-cost()
}
}
fun lucky-draw()
{
with fun check-cost() { 0 } // initial cost
with handler {
return(x) {[x]}
control eat-icecream() {
val current-cost = check-cost();
val cost-lucky = {
with override fun check-cost(){current-cost + 1}
resume(())
};
val cost-unlucky = {
with override fun check-cost(){current-cost + 3}
resume(())
};
cost-lucky ++ cost-unlucky
}
}
my-eat-icecream()
}
// fun lucky-draw()
// {
// var total-cost := 0;
// with fun check-cost() { total-cost }
// with handler {
// return(x) {[x]} // transform the return value into a list
// control eat-icecream() {
// total-cost := total-cost + 1;
// val cost-lucky = resume(())
// total-cost := total-cost - 1;
// total-cost := total-cost + 3;
// val cost-unlucky = resume(())
// total-cost := total-cost - 3;
// cost-lucky ++ cost-unlucky // concatenate two lists
// }
// }
// my-eat-icecream()
// }
fun buffet() {
with fun eat-icecream() { () } // the eat-icecream handler does nothing
with fun check-cost() { 2 } // the check-cost handler always returns 2
my-eat-icecream()
}
fun flat-pricing(price: int) {
var total-cost := 0;
with fun eat-icecream() { total-cost := total-cost + price }
with fun check-cost() { total-cost }
my-eat-icecream()
}
effect fun add-cost(cost: int) : ()
fun decreasing-pricing(price: int) {
var current-price := price;
with fun eat-icecream() {
add-cost(current-price);
if (current-price > 0) {
current-price := current-price - 1
}
}
my-eat-icecream()
}
fun decreasing-pricing-full(price: int) {
var total-cost := 0
with fun check-cost() { total-cost }
with fun add-cost(price) {
total-cost := total-cost + price
}
decreasing-pricing(price)
}
fun with-fbi() {
var innocent := False;
with control eat-icecream() {
if (!innocent) {
val is-suspect = choose(True, False) // toss a coin
if ( is-suspect ) {
println("🚓"); // no more ice-creams for you!
return 0 // of course we won't charge you for any
// ice-cream, if that matters to you
} else {
innocent := True;
resume(()) // you can keep on eating ice-creams
}
} else {
resume(()) // We already know that you're not a suspect
}
}
with fun check-cost() { 2 } // buffet
my-eat-icecream()
}
fun main() {
println(buffet()); // prints 2
println(flat-pricing(1)); // prints 2, i.e. two $1 ice-creams
println(flat-pricing(3)); // prints 3, i.e. a $3 ice-cream
println(decreasing-pricing-full(2)); // prints 3, i.e. a $2 and a $1 ice-cream
println(with-fbi()); // prints 0 or 2, depending on the cop's coin toss
with total-cost = lucky-draw().foreach
println(total-cost) // prints 2, 4, 6
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment