Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/implicits #69

Merged
merged 98 commits into from
Mar 3, 2019
Merged

Feature/implicits #69

merged 98 commits into from
Mar 3, 2019

Conversation

b-studios
Copy link
Member

This PR encodes implicit parameters using algebraic effects.

PR for discussion. Replaces #68. See original PR for more discussion.

@b-studios
Copy link
Member Author

b-studios commented Jun 12, 2018

With first class implicit handlers we now can write code like

// forall<a,e>. (() -> <?x|e> a) -> e a
val x = implicit (?x = 3)
// forall<a,e>. (() -> <?x,?y|e> a) -> e a
val xy = implicit (?x = 3, ?y = 4)

effect reader<a> { fun read() : a }

// forall<a,e>. (() -> <?x,reader<int>|e> a) -> e a
val read42 = implicit (read = 42, ?x = read())

val res2 = {
  using implicit (?x = 3)
  ?x + ?x
}

EDIT: This syntax is mostly deprecated as the proposal moved on.

@b-studios
Copy link
Member Author

b-studios commented Jun 12, 2018

With the new lazy implicit handler declarations, we can write code like:

implicit (?x = { println("asked for x"); 42 }) { ?x + ?x }

which will evaluate the body in braces every time the implicit argumentis being used. However, note that this is driven syntactically and thus is not equal to

fun getX() { println("asked for x"); 42  }
implicit (?x = getX) { ?x + ?x }

which will bind the function getX to the implicit argument.

In contrast

...
implicit (?x = getX()) { ?x + ?x }

will be eagerly evaluated and trigger the side effects once.

EDIT: This syntax is mostly deprecated as the proposal moved on.

@b-studios
Copy link
Member Author

b-studios commented Jul 27, 2018

The latest changes now allow syntax like the following:

effect dimensions {
  val width : int
  val height : int
}

implicit fun test(a: int): int

implicit val test2: int

val h = handler {
  fun test2() { 42 }
}

val h2 = handler {
  val test2 = 43
}

Still missing:

  • value effect operations don't evaluate the value once, but are currently just desugared into tail resumptions
  • there is no connection between value declarations, value definitions and value usage. The different syntaxes can just be mixed. We need to annotate the effect operation with a value-label and extend the typechecker to assert that value definitions (i.e. val x = 42) and value-usage (i.e. just x instead of x()) only can be used for declared value effects.

@b-studios
Copy link
Member Author

b-studios commented Aug 2, 2018

@daanx The latest commit (e3f96ab) introduced the biggest breaking change: Dynamically bound functions are tail resumptive per default. (edit: commit a3ccdf6 now also adjusts the tests accordingly)

handler {
  fun op() { /* ... no resume here ... */ }
}

To actually get access to the continuation we now need to prefix the function with effect:

handler {
  effect fun op() { /* ... resume now available ... */ }
}

Right now, this change prevents changing the state of a parametrized handler in a dynamically bound function (since resume is not available). To change the state, the effect fun needs to be used for now.

@b-studios
Copy link
Member Author

Using ? as part of an identifier is mostly independent of this proposal, so I am gonna move these changes to a separate pull request.

@daanx daanx merged commit dd55ddb into dev Mar 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants