matijapretnar / eff Goto Github PK
View Code? Open in Web Editor NEWA functional programming language based on algebraic effect handlers
Home Page: http://www.eff-lang.org/
License: BSD 2-Clause "Simplified" License
A functional programming language based on algebraic effect handlers
Home Page: http://www.eff-lang.org/
License: BSD 2-Clause "Simplified" License
There is no tutorial/overview comparing the advantages of eff to other ways of describing IO in Ocaml. This would be helpful to discuss the advantages.
In the Non-determinism example on the website, the backtrack handler code is written like this
let backtrack = handler
| effect Decide k ->
(* We use a second handler to handle the continuation. *)
handle continue k false with
| effect Fail _ -> continue k true
;;
However, it seems to me, that the paper defines it like follows
let backtrack = handler
| effect Decide k ->
(* We use a second handler to handle the continuation. *)
handle continue k true with
| effect Fail _ -> continue k false
;;
Notice that the continuations are reversed
When I try loading the code in the REPL, the handler behaves correctly (I believe), even though the code shown above the REPL is wrong.
I am not sure whether this is a misunderstanding on my side or a bug, but I would be appreciative if someone could take a look at it.
Hello all!
Thank you in advance for any help!
I was wondering whether or not it is possible to read and write to files in Eff?
When trying to use the version built from current main
(65a4cec190591c43ff75779f68dbcdc966689349
) for the benchmarks at https://github.com/effect-handlers/effect-handlers-bench , all OCaml builds fail with type errors.
Is there a more recent version than the OOPSLA2021 Artifact that can be used to build and run those benchmarks (or different ones)?
Alternatively, how could one go about reasonably benchmarking the current version?
in text:
File "benchmarks/001_nqueens/generated_001_nqueens.ml", line 73, characters 18-33:
73 | _safe_50 _x_105 >>= fun _b_176 ->
^^^^^^^^^^^^^^^
Error (warning 5 [ignored-partial-application]): this function application is partial,
maybe some arguments are missing.
File "benchmarks/001_nqueens/generated_001_nqueens.ml", line 73, characters 18-33:
73 | _safe_50 _x_105 >>= fun _b_176 ->
^^^^^^^^^^^^^^^
Error: This expression has type int -> 'a
but an expression was expected of type 'b computation
File "benchmarks/002_generator/generated_002_generator.ml", line 87, characters 5-65:
87 | (fun (_x_85 : unit -> generator computation) -> Value _x_85))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression should not be a function, the expected type is
unit OcamlHeader.computation
File "benchmarks/003_tree_explore/generated_003_tree_explore.ml", line 174, characters 13-80:
174 | (fun (_x_161 : int -> (int * intlist) computation) -> Value _x_161))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression should not be a function, the expected type is
int OcamlHeader.computation
File "benchmarks/004_triples/generated_004_triples.ml", line 143, characters 5-41:
143 | (fun (_x_156 : int) -> Value _x_156))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression should not be a function, the expected type is
int OcamlHeader.computation
File "benchmarks/007_simple_counter/generated_007_simple_counter.ml", line 86, characters 13-49:
86 | (fun (_x_175 : int) -> Value _x_175))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression should not be a function, the expected type is
int OcamlHeader.computation
That is, eff runs successfully, but the resulting OCaml code does not compile.
This also happens with any example I try to write myself, as soon as it uses any effects, e.g.:
effect Emit : int -> unit
let main =
handle
perform (Emit 3); 0
with
| effect (Emit i) k -> k ()
with wrapper code
let _ = Printf.printf "%d\n" (Generated_eff_primes.main)
and using the Build structure from https://github.com/effect-handlers/effect-handlers-bench also fails with
File "primes_eff/generated_eff_primes.ml", line 42, characters 5-39:
42 | (fun (_x_53 : int) -> Value _x_53))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This expression should not be a function, the expected type is
int OcamlHeader.computation
Does EFF support for JSON conversions. This includes converting files/strings/classes to dictionaries; and dictionaries to json formatted strings ?
If in pervasives.eff we do this (notice r#print _ k
):
let state r x = handler
| val y -> (fun _ -> y)
| r#print _ k -> (fun s -> k s s)
| r#update s' k -> (fun _ -> k () s')
| finally f -> f x;;
then eff 3.0 hangs.
If you enter a list such as [1; 2; 3]
, the closing bracket is missing. Things get weirder with nested lists. The problem seems to lie in the color formatting syntax of jQuery terminal.
reddit thread:
https://www.reddit.com/r/haskell/comments/8ldmwu/question_about_algebraic_handler/
so I have the following code, and it expectingly fail, but is runtime failure
effect Fail : empty (* This is equivalent to the type unit -> empty. *)
effect Decide : bool
let fail () = absurd (perform Fail) (* Equivalent to perform (Fail ()). *)
let decide () = perform Decide
let const x y = x
;;
let hfail = handler
| x -> Some x
| effect Fail k -> None
let hdecide = handler
| x -> (fun b -> if b then x else x)
| effect Decide k -> (fun s -> continue k s s)
;;
let res = with hdecide handle with hfail handle
let x = decide () in
if x then fail () else 10
in res false
;;
let res = with hfail handle with hdecide handle
let x = decide () in
if x then fail () else 10
in
match res with
| Some x -> x true
| None -> 100
;;
let x = fail ()
also fail, but according to the paper it could be cought.
what about the above large piece of code?
Hi, I'm not familiar with the literature, and my naive searches lead to nothing so far. This may not be a new idea, if it's been experimented with I'd love get pointers. This may also be off base...
A natural extension of typed effects would be to let users articulate grammars. E.G. for file operations, with a RegExp-like syntax, Open(Read|Write)*Close
would prevent one from writing to a file that hasn't been opened yet (I know there are better ways to enforce this, this is for the sake of the example).
This would enable one to ensure at compile time that a piece of code respects a given protocol (e.g. that you can't write HTTP headers while the body is being sent).
Hello all,
Is there a way I can get the pre-defined types and operations?
For example,
For lists, is there a library for lists that I can import easily or I do I have to copy any definition I need into my file?
I am now struggling with Ref type
"Then, to learn more about the theoretical background, you can read [An Introduction to Algebraic Effects and Handlers]."
An Introduction to Algebraic Effects and Handlers
tia
~A
Hello all,
Are there new instructions for compilation?
I am having some compilation errors
ocaml setup.ml -build
+ ocamlfind ocamlopt -package unix -package ocamlbuild -linkpkg -package js_of_ocaml.ocamlbuild myocamlbuild.ml /usr/local/Cellar/ocamlbuild/0.12.0/lib/ocamlbuild/ocamlbuild.cmx -o myocamlbuild
ocamlfind: Package `js_of_ocaml.ocamlbuild' not found
Command exited with code 2.
Compilation unsuccessful after building 1 target (0 cached) in 00:00:00.
E: Failure("Command ''/usr/local/bin/ocamlbuild' src/eff.native -use-ocamlfind -plugin-tags 'package(js_of_ocaml.ocamlbuild)' -tag debug' terminated with error code 10")
make: *** [build] Error 1
Eff looks really cool, very excited to check it out. Trying to get it building locally on OSX by following the README, but running into an issue:
$ ./configure
E: Field 'findlib_version' is not set: Field 'ocamlfind' is not set
How do you set those variables? Google didn't give anything, though https://ocaml.org/docs/install.html#Debian shows:
apt-get install ocaml-findlib
Is it required to install findlib
on the Mac? How did you get it working, are you running on Linux or a Mac?
I got ocaml setup with homebrew:
$ brew install ocaml
$ brew install opam
$ brew install menhir
$ ocaml -version
The OCaml toplevel, version 4.02.1
Any ideas?
When throwing away instances, resources for built-in effects got thrown away as well. We should add at least the one for print to be able to write interesting examples.
Go to the Try Eff page.
Go to the Probability example
Hit "Load File"
Expected behaviour: file loads successfully.
Actual behaviour:
Warning (line 11, char 19):
This pattern-matching is not exhaustive.
Here is an example of a value that is not matched:
val uniform : 'a list -> 'a = <fun>
Typing error (line 22, char 16):
Unbound operation Random_float
#
Line 7 in 4c6bc57
Many of the functions in assoc.ml
can be proxied to OCaml stdlib:
Assoc.lookup
=> List.assoc_opt
Assoc.remove
=> List.remove_assoc
Assoc.iter
=> List.iter
(has been done)Assoc.kmap
=> List.map
Assoc.fold_left
=> List.fold_left
(has been done)Assoc.fold_right
=> List.fold_right
(has been done)Assoc.length
=> List.length
(has been done)and so on. Is there a reason these are re-implemented by hand?
I get the following error when attempting to install Eff via OPAM on macOS.
# File "src/parsing/lexer.mll", line 62, characters 36-37:
# Error: This expression has type string but an expression was expected of type
# bytes
# Command exited with code 2.
### stderr ###
# E: Failure("Command ''/Users/walkie/.opam/system/bin/ocamlbuild' src/eff.native -tag debug' terminated with error code 10")
# make: *** [build] Error 1
Here's the full output of OPAM, which includes the versions of dependencies: OPAM-Eff.txt
I'm having a hard time to figuring out, in case the computation is spawning multiple threads, what should happen when one or more of those threads is throwing an exception? If the exception handler is provided after the fork, that feels quite normal, but if the exception handler is provided before the fork, should the thrown exceptions trigger multi-shots of the exception handler ?
I kinda see traditional wisdom is to prevent exceptions from crossing fork boundaries, but that seems guilty for go statement considered harmful.
I wonder how this is reasoned with algebraic effects based exception handling, some clue please ?
Btw I don't know either if a finally
block can be implemented as an effect, and if it can be implemented, I feel it even more subtle to have a multi-shot finally
block.
On the other hand, I feel the said goto
semantic of go
statement can be fixed if exceptions can cross fork boundaries and properly settled.
type value =
| Const of Const.t
| Tuple of value list
| Record of (OldUtils.field, value) Assoc.t
| Variant of OldUtils.label * value option
| Closure of closure
| Handler of (result -> result)
I was trying to use Split as an external function
I got it to work but the return value is of this type (Tuple of value list)
However, I want to return a string list instead of tuple
I tried to make a new constructor for lists but still the value retuned comes as a tuple
type value =
| Const of Const.t
| Tuple of value list
| List of value list
| Record of (OldUtils.field, value) Assoc.t
| Variant of OldUtils.label * value option
| Closure of closure
| Handler of (result -> result)
Any ideas?
Thanks,
Ghadeer
It seems that effects are missing from types.
Using the Eff REPL, when loading a file containing:
effect Whatever : int
let foo x = let bar y = perform Whatever in bar ;;
The REPL produces this output:
val foo : 'a -> 'b -> int = <fun>
It seems to me that there are missing effects on the function type.
I would expect the part !{Whatever}
to be there to show that the function foo
performs an effect when applied to its second argument.
There are a number of Eff versions floating around. The homepage should contain a list of all versions, short description of their differences, and corresponding research papers.
Ignoring 372 variants (see #30) of Eff floating around, both Eff and Multicore OCaml both offer algebraic effects and handlers with slightly different syntax. I guess there is no syntax so brilliant that it would outweigh the convenience of just taking one source code and putting it into the other language. Since Multicore OCaml is the bigger one here, I suggest Eff adopts their syntax. The necessary changes are
effect Eff : ...
- we did this some time agoperform (Eff x)
rather than #Eff x
- in the long run, we'd also want perform EffWithNoArgs
and need the type 'a eff
, but in the short run, this just needs some slight changes in the parsercontinue k x
rather than k x
- I don't want to make a distinction between functions and continuations, so I suggest to define continue
as the identity functionI don't know whether to keep the old syntax for handlers or not, but maybe I'd issue a warning if it is used as it will make the code incompatible with Multicore OCaml. I would do the same if someone forgot to write continue
when resuming the continuation. There will always be incompatibilities because OCaml offers so much other stuff, but at least this will give us some guarantees for small effectful examples.
@kayceesrk, @lpw25 - What do you think and did I miss anything?
Hello all,
I am having an issue with using Characters in Eff
Whenever I use it, it says "unrecognised symbol" or "parser error"
The main reason why I want to use it is to be able to use the Split function from OCaml
external split_on_char : char -> string -> string list = "split_on_char"
I did everything to add Char as a type and it compiled << you can see that in my Pull-request
but I noticed that it cannot parse Char properly << maybe the single quote is the problem
let m = '4';;
let k = 's' ;;
Equality does not imply the inequality of the types of the expressions that are compared.
eg the inferred type of
let f x y = x = y
is a -> b -> bool instead of a -> a -> bool
Both the website's REPL and the local build from the master do nothing on the #type
command.
Here's what I tried on both, the website and the local REPL :
#type 23 ;;
The terminal just eats the input and prints a newline.
I'd like to have your comment about how much I can imitate algebraic effects with an imperative, interpreted language.
Currently in my mind is a perform
keyword, prefixing to an expression, so if I resolve function (or procedure, more precise for a procedural language) calls in it, against the call stack, instead of the lexical context of the direct enclosing function/procedure, I kinda feel it implements a sort of algebraic effect call, given the language having pattern matching feature for a calling-site, to dispatch or propagate (to outer frames on the call stack) the effect call.
What's your comment about this idea?
I built eff from source ./configure && make
, and tried to run the example
$ ./eff examples/choice.eff
Syntax error (file "examples/choice.eff", line 6, char 15):
running the tests work, and running the example on the interactive tutorial website works as well.
I've found that the difference is, in the examples effects are declared like so
type 'a random = effect
operation pick : ('a * float) list -> 'a
end
whereas the tests have
effect Decide : unit -> bool;;
Did I miss any step? Thanks!
We are no longer able to compile the current js_of_ocaml
toplevel. Let's replace it with a new one, preferrably built with Bucklescript.
Sorry for abusing the issue system for a question. Once effect handlers are implemented in OCaml, would it be possible to simply compile Eff to OCaml Lambda (using, for example, [Malfunction])(https://github.com/stedolan/malfunction), and let the runtime do the rest?
While cleaning up the desugaring I had some trouble with the way the variables interact in the let case.
Turns out there is a problem:
let a = 1 and b = a + 1 in b
The above code complains about not knowing the variable a
in the second part.
Also, using fold_right
seems like an odd choice to me, as the following complains about not knowing the variable a
first:
let x = 1 and y = x + 1 and a = 1 and b = a + 1
I tried switching it to fold_left
but with no success.
We should use records like in UntypedSyntax
instead of pairs.
When executing the threads example in the browser it just dies silently. The only things that seems to be processed is queue
. This is especially embarrasing as I am typing this in class, with all the students watching.
This expression has a forbidden cylclic type
cylclic -> cyclic
in:
src/typing/simple/simpleUnify.ml line 14
The interpreter at https://www.eff-lang.org/try/ displays:
Runtime error: unknown external symbol infinity.
this makes it impossible to run any of the code in the tutorial.
Expressions with (what would be) recursive types cause the type checker to loop, e.g.
#type let rec f x = f in f;;
Here is my Opam setup:
$ env | grep opam
CAML_LD_LIBRARY_PATH=/usr/local/opam/4.01.0/lib/stublibs
MANPATH=/usr/local/opam/4.01.0/man:
PERL5LIB=/usr/local/opam/4.01.0/lib/perl5
OPAMROOT=/usr/local/opam
OCAML_TOPLEVEL_PATH=/usr/local/opam/4.01.0/lib/toplevel
PATH=/usr/local/opam/4.01.0/bin:/Library/Frameworks/Python.framework/Versions/3.4/bin:/Users/andrej/bin:/Users/andrej/.cabal/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/opt/X11/bin:/usr/local/MacGPG2/bin:/usr/texbin
I am on master branch of Eff, commit 5ad3b54.
When I run ./configure
it gets wrong the directory in which Ocaml binaries are found:
$ ./configure
Configuration:
ocamlfind: ........................................... /usr/local/opam/system/bin/ocamlfind
ocamlc: .............................................. /usr/local/bin/ocamlc.opt
ocamlopt: ............................................ /usr/local/bin/ocamlopt.opt
ocamlbuild: .......................................... /usr/local/bin/ocamlbuild
And so compilation fails:
$ make
ocaml setup.ml -build
Finished, 1 target (0 cached) in 00:00:00.
/bin/sh: /usr/local/opam/system/bin/ocamlfind: No such file or directory
Failure: Error while running: /usr/local/opam/system/bin/ocamlfind list.
Compilation unsuccessful after building 0 targets (0 cached) in 00:00:00.
E: Failure("Command ''/usr/local/bin/ocamlbuild' src/eff.native -tag debug' terminated with error code 2")
make: *** [build] Error 1
I am trying to do an effect that returns a tuple
but I am not able to figure out the syntax
effect Choice : unit -> (string, bool);;
Previously, I had something like
type 'a choice = effect
operation findChoice : unit -> 'a
end;;
but with the new syntax, I am not able to pass 'a
I appreciate your help
Thanks,
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.