-
Notifications
You must be signed in to change notification settings - Fork 9
Adding state example for Koka #2
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| # Assuming the Koka folder is a peer of effects-rosetta-stone | ||
| KOKA ?= ../../../../koka/out/debug/koka-0.9.0-dev | ||
|
|
||
| all: | ||
| $(KOKA) state.kk | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,74 @@ | ||
| // A state effect that is polymorphic in the state of type `a` | ||
| effect state<a> { | ||
| fun get() : a | ||
| fun put( x : a) : () | ||
| } | ||
|
|
||
| // We define first a state handler using functions. | ||
| // But you would never do this in practice in Koka! -- | ||
| // use a parameterised handler instead: see `fun state` for that. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes yes, we know that, and we will have a separate example to point this out. It's still worth having a comment explaining there's another way in Koka. |
||
| // | ||
| // inferred type: forall<a,b> (init : a, action : () -> state<a> b) -> b | ||
| fun fstate(init,action) { | ||
| (handle(action) { | ||
| get() -> fun(st){ resume(st)(st) } | ||
| put(x) -> fun(st){ resume(())(x) } | ||
| return x -> fun(_st){ x } | ||
| })(init) | ||
| } | ||
|
|
||
|
|
||
| fun example1a() { | ||
| // In koka an anonymous function without arguments can be written | ||
| // with just braces (and passed outside the argument parenthesis) | ||
| fstate(10) { | ||
| val x = get() | ||
| put(4 + x) | ||
| 3*get() | ||
| } | ||
| } | ||
|
|
||
| fun example1b() { | ||
| // Koka has `using` syntactic sugar to make the rest of the scope | ||
| // the anonymous function argument, and this is equivalent to the | ||
| // previous example. | ||
| using fstate(10) | ||
| val x = get() | ||
| put(4 + x) | ||
| 3*get() | ||
| } | ||
|
|
||
| fun example2() | ||
| { | ||
| fun add-to(x : int) { | ||
| put(get() + x) | ||
| } | ||
| using fstate(0) | ||
| for(1,100,add-to) | ||
| get() | ||
| } | ||
|
|
||
| // Here we use a paremeterised handler with a local state `st` | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. From here onwards the code should be moved to a separate example which is exactly like this example but it uses parameterized handlers. See #3 for discussion on creating such an example.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I disagree. We should be comparing idiomatic code from each language. The idiomatic version of simple state in Koka and Links uses parameterised handlers. The idiomatic version of simple state in Frank uses shallow handlers. The description of the example should be flexible enough (and perhaps updated) in order to accommodate different idioms. I think it is more valuable to highlight the differences in features between languages rather than stressing the lowest common denominator. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There should be multiple examples: idiomatic usage, as well as trying to impose the same structure in multiple languages, with a careful readme that helps the reader navigate through them. You well know that one learns much by trying to faithfully express one collection of abstractions using another ;).
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That certainly makes sense sometimes, but the idiomatic version should be the primary one. Daan did include the crippled version in Koka too. For Frank it is simply not possible to express the Eff version because Frank does not have deep handlers (and I'm sure the same issue will crop up with other languages and features). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Great! Then there should be a description of Frank's inability to do so with deep handlers. This kind of comparison is exactly the kind of examples and non examples this repo is for. Similarly, there should be a corresponding shallow handler example in effect demonstrating how awkward it is in Eff.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You misunderstand. There is absolutely a place for the kind of commentary you describe. But, placing each minor variant of state in a different directory (rather than in the same file, as @daanx did), is too fine a level of granularity for my taste. More generally, if we are too fussy then people won't bother submitting any examples. I think it would be better to err on the side of accepting mildly ill-formed examples rather than rejecting them and then losing the goodwill of the submitters. We can always curate them and add further commentary after the fact. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not different directory, but different example files all grouped under the same 'state' directory.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @slindley has a point: too fina a granularity is cumbersome. However, we should ensure that code gets compared, rather than just demonstrated. It's the Rosetta stone after all. How about this: if there are several natural ways of implementing an effect, they should all be collected under the same example and compared. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe following the example of Rosettacode might be useful here? They seem to allow for having a few different implementations per language, if the different versions help demonstrate the interesting qualities of the language.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I agree with @slindley here: for each example problem, first provide the idiomatic version, and then, if applicable, also provide another approach. When I am looking to compare, I would like to see the idiomatic versions first, not crippled ones just for the sake of emulating other approaches. I think it is better to provide higher level challenge problems instead of requiring the exact same language features. For example, do an example with producer/consumer where Frank can shine with shallow handlers + multi handlers, where Koka would need to get by in some other way; that is really interesting to compare from my perspective. Anyway, just my 2c, I am already very grateful that this repository is set up. |
||
| // The last argument to `resume` contains the new local state | ||
| // under which to resume. This is *much* more efficient than | ||
| // the previous `fstate` handler that builds explicit functions. | ||
| // inferred type: | ||
| // forall<a,b,e> (st : a, action : () -> <state<a>|e> b) -> e b | ||
| val state = handler(st) { | ||
| get() -> resume(st,st) | ||
| put(x) -> resume((),x) | ||
| } | ||
|
|
||
| fun example1c() { | ||
| using state(10) | ||
| val x = get() | ||
| put(4 + x) | ||
| 3*get() | ||
| } | ||
|
|
||
| fun main() { | ||
| example1a().println | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it necessary to print things? If we can get Koka toplevel to just show us the values of computed examples, it might be better not to print. Printing is an effect, and so in a sense it pollutes the example. |
||
| example1b().println | ||
| example2().println | ||
| example1c().println | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a bad assumption. A better assumption is that
kokais in the path, so I would just saykokahere. If it's not in the path, it will be passed to theMakefilefrom the outer environment.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. However, if one just installs koka and runs
jake, it currently only buildskoka-0.9.0-dev, so the user then needs to makekokaan alias or something? Should I change koka's build to create a plainkokaexecutable too?