Understanding the API of multi-prompt delimited continuations - functional-programming

An API for multi-prompt delimited continuations is described in the paper Delimited Control in OCaml, Abstractly and Concretely System Description.
My question concerns the type of push_subcont : ('a,'b) subcont -> (unit -> 'a) -> 'b. Why is this type not ('a,'b) subcont -> 'a -> 'b? Furthermore, why is there a separate type for subconts: why not simply ('a,'b) subcont = 'a -> 'b? I'm almost certain there is a good reason for that, because Oleg makes things as elegant as possible (but not more elegant).
Thanks!

Why not ('a,'b) subcont -> 'a -> 'b?
I think it is for the same reason as for push_prompt -- which is easier to understand. push_prompt p (fun () -> e) is intuitively a form of try e with p: the prompt p is placed on the stack as a handler, and e runs under this handler. If you used push_prompt p e instead, a strict language would evaluate the arguments p and e first, and e would run and "raise exceptions" before the prompt is set.
push_subcont sk (fun () -> e) could have the same kind of problems: it is a kind, intuitively, of "restart the computation sk that was interrupted by an exception". It is important that e is run inside the context of the computation, rather than outside it, for example if it wishes to raise exceptions corresponding to handlers installed by sk.
Why not simply ('a,'b) subcont = 'a -> 'b?
That could be done if there was only one way to restart subcontinuations: they could be returned "pre-restarted", under the form of functions that, when applied, restarts with the given argument.
But that is not the case: there are push_subcont and push_delim_subcont, described at the end of the article, that have different semantics. The "caller" should choose which restart technique to use. They both need to access internal data of the subcontiuation, so they could not operate on the subcontinuation-as-function representation.

Related

Ocaml - Runtime compilation of code as a string

I want to parse and compile a function that I have written at runtime, for example I have the following string I generated at runtime:
let str = "fun x y z -> [x; y; z;]"
I am looking for something that will allow me to do something similar to:
let myfun = eval str
(* eval returns the value returned by the code in the string so myfun will
have the type: 'a -> 'a -> 'a -> 'a list*)
Is there a way to do that in OCaml? I came across Dynlink but I am looking for a simpler way to do it.
There is no easier solution than compiling the code and Dynlinking the resulting library.
Or equivalently, one can use the REPL, write the string to the file system and them load it with #use.
Depending on your precise use case, MetaOCaml might be an alternative.
Another important point is that types cannot depend on values in a non-dependently typed language. Thus the type of eval needs to be restricted. For instance, in the Dynlinking path, the type of dynamically linked functions will be determined by the type of the hooks used to register them.

Storing user input information in functional programming (Erlang) using only immutable variables

As a beginner in Erlang, I am working my way through the Programming Erlang book (2nd ed). I have a very hard time grasping how to store and periodically update external information (such as intermittent user input) using the principles of functional programming exclusively.
To take my present example, I am now in the beginning of the concurrent programming section (Chapter 12) where the book talks about the area server. Below is my variant of it.
As an exercise, I am trying to add to this module a way to store all the requests the user makes. But despite having a bit of experience with recursive programming the lack of mutable variables, in the sense of imperative languages, seems to be crippling in this particular instance.
I have tried looking up a few related resources on SE sites such as mutable state in functional programming and
immutability in fp but it doesn't really answer my question in a practical way. I know that what I am trying to accomplish can be done by use of the ETS (or even a database), or by using the process-memory of a new process which receives and maintains the history within itself.
But what I would really like to understand (and the point of this question) is if this can be accomplished using generic functional programming principles without having to use Erlang-specific tools. The commented out lines in the code segment indicate what I am naively expecting the first steps to look like.
-module(geometry_server4).
-export([start/0, client/2, loop/0]).
start() ->
spawn(geometry_server4, loop, []).
client(Pid_server, Geom_tuple) ->
Pid_server ! {self(), Geom_tuple},
%ok = storerequests(Geom_tuple),
receive
{area, Pid_server, Area} -> io:format("Client: Area of ~p is ~p~n", [Geom_tuple, Area]);
{error, Error} -> io:format("~p~n", [Error])
end.
%storerequests(Geom_tuple) -> addtolist(Geom_tuple, get_history()).
%
%addtolist(Item, History) ->
% [Item | History].
%get_history() -> ???
loop() ->
receive
{Client, {rectangle, S1, S2}} ->
Area = S1 * S2,
Client ! {area, self(), Area},
loop();
{Client, {square, S}} ->
Area = S * S,
Client ! {area, self(), Area},
loop();
{Client, _} ->
Client ! {error, "invalid parameters"},
loop()
end.
Based on the book, this toy server gets called in the terminal as:
1> c(geometry_server4).
2> P = geometry_server4:start().
3> geometry_server4:client(P, {square, 3}).
But what I would really like to understand (and the point of this
question) is if this can be accomplished using generic functional
programming principles without having to use Erlang-specific tools.
Yes, it can. You can use a loop variable to store what's known as the state.
First, a couple of preliminary points:
Don't post code with line numbers. You want someone to be able to copy your code and paste it in their text editor and be able to run the code.
In erlang, by convention you use camel case for variable names, such as ServerPid.
For your own sanity, don't use module names that are more than two letters long.
Consider putting all your server code in one portion of the file, and all the client code in another portion of the file. Your client code is in the middle of the server code.
-module(my).
%%-export([setup/1]).
-compile(export_all).
%%-include_lib("eunit/include/eunit.hrl").
%%
start() ->
spawn(my, loop, [[]]).
loop(History) ->
receive
{Client, {rectangle, S1, S2}=Tuple} ->
Area = S1 * S2,
Client ! {area, self(), Area},
loop([Tuple|History]); %Add Tuple to the history
{Client, {square, S}=Tuple} ->
Area = S * S,
Client ! {area, self(), Area},
loop([Tuple|History]);
{Client, history} ->
Client ! {history, self(), History},
loop([history|History]);
{Client, Other} ->
Client ! {error, self(), "invalid parameters"},
loop([{error, Other}|History])
end.
client(ServerPid, Req) ->
ServerPid ! {self(), Req},
receive
Reply -> io:format("~p~n", [Reply])
end.
test() ->
ServerPid = start(),
Requests = [
{rectangle, 2, 3},
{square, 4},
history,
"hello",
history
],
send_requests(Requests, ServerPid).
send_requests([], _) ->
done;
send_requests([Req|Reqs], ServerPid) ->
client(ServerPid, Req),
send_requests(Reqs, ServerPid).
In the shell:
1> c(my).
{ok,my}
2> my:test().
{area,<0.64.0>,6}
{area,<0.64.0>,16}
{history,<0.64.0>,[{square,4},{rectangle,2,3}]}
{error,<0.64.0>,"invalid parameters"}
{history,<0.64.0>,[{error,"hello"},history,{square,4},{rectangle,2,3}]}
done
3>

How can I get this function to be tail-recursive?

I'm still trying to implement 2-3 finger trees and I made good progress (repository). While doing some benchmarks I found out that my quite basic toList results in a StackOverflowException when the tree ist quite large. At first I saw an easy fix and made it tail-recursive.
Unfortunately, it turned out that toList wasn't the culprit but viewr was:
/// Return both the right-most element and the remaining tree (lazily).
let rec viewr<'a> : FingerTree<'a> -> View<'a> = function
| Empty -> Nil
| Single x -> View(x, lazyval Empty)
| Deep(prefix, deeper, One x) ->
let rest = lazy (
match viewr deeper.Value with
| Nil ->
prefix |> Digit.promote
| View (node, lazyRest) ->
let suffix = node |> Node.toList |> Digit.ofList
Deep(prefix, lazyRest, suffix)
)
View(x, rest)
| Deep(prefix, deeper, Digit.SplitLast(shorter, x)) ->
View(x, lazy Deep(prefix, deeper, shorter))
| _ -> failwith Messages.patternMatchImpossible
Looking for the only recursive call it is obvious that this is is not tail-recursive. Somehow I hoped this problem wouldn't exist because that call is wrapped in a Lazy which IMHO is similar to a continuation.
I heard and read of continuations but so far never (had to) use(d) them. I guess here I really need to. I've been staring at the code for quite some time, putting function parameters here and there, calling them other places… I'm totally lost!
How can this be done?
Update: The calling code looks like this:
/// Convert a tree to a list (left to right).
let toList tree =
let rec toList acc tree =
match viewr tree with
| Nil -> acc
| View(head, Lazy tail) -> tail |> toList (head::acc)
toList [] tree
Update 2: The code that caused the crash is this one.
let tree = seq {1..200000} |> ConcatDeque.ofSeq
let back = tree |> ConcatDeque.toList
The tree get built fine, I checked and it is only 12 levels deep. It's the call in line 2 that triggered the overflow.
Update 3: kvb was right, that pipe issue I ran into before has something to do with this. Re-testing the cross product of debug/release and with/without pipe it worked in all but one case: debug mode with the pipe operator crashed. The behavior was the same for 32 vs. 64 bit.
I'm quite sure that I was running release mode when posting the question but today it's working. Maybe there was some other factor… Sorry about that.
Although the crash is solved, I'm leaving the question open out of theoretical interest. After all, we're here to learn, aren't we?
So let me adapt the question:
From looking at the code, viewr is definitely not tail-recursive. Why doesn't it always blow up and how would one rewrite it using continuations?
Calling viewr never results in an immediate recursive call to viewr (the recursive call is protected by lazy and is not forced within the remainder of the call to viewr), so there's no need to make it tail recursive to prevent the stack from growing without bound. That is, a call to viewr creates a new stack frame which is then immediately popped when viewr's work is done; the caller can then force the lazy value resulting in a new stack frame for the nested viewr call, which is then immediately popped again, etc., so repeating this process doesn't result in a stack overflow.

Can I do `type 'a entry = string * 'a * 'a entry;;` in OCaml?

It seems I can't.
I wanna understand why I can't.
It is sure that I can do type 'a entry = Empty | Value of string * 'a * 'a entry;;, so if I want to recursively define a type, I only can go the union route?
Your question is confusing because it only mentions the type you don't want to use! However, I see from your title that you want to use a directly recursive type.
If you want directly recursive types, you need to turn on -rectypes on the command line. This is not something you really want to do most of the time, however. It allows too many types that really aren't what you want.
$ ocaml
OCaml version 4.00.0
# type 'a entry = string * 'a * 'a entry;;
Error: The type abbreviation entry is cyclic
# ^D
$ ocaml -rectypes
OCaml version 4.00.0
# type 'a entry = string * 'a * 'a entry;;
type 'a entry = string * 'a * 'a entry
#
The reason -rectypes isn't enabled by default is that it allows types to be given to many expressions that are actually coding errors. On balance, the extra flexibility isn't worth giving up the extra error detection.
Here's an example I found in an old OCaml mailing list message:
$ ocaml -rectypes
OCaml version 4.00.0
# let f x = x :: x;;
val f : ('a list as 'a) -> 'a list = <fun>
#
With -rectypes turned on, this fairly absurd function is accepted. But really it only works on rather strange list types. Most likely the programmer meant to append the list to itself using # rather than ::. Unfortunately this error won't be detected until much later when -rectypes is on.
As a side comment, and as newacct points out, you would probably soon find that the type in the title isn't so useful. It really can only represent cyclic or infinite structures. This is another reason that working without -rectypes isn't too difficult.
When you do type something = another type, you are doing a type synonym, like a typedef in C. It makes an alias that you can use as a shortcut to refer to another type. It does not define a new type by itself. Hence, it cannot be recursive.
When you do type something = SomeContructor of ..., that defines a new algebraic data type. This can be recursive.
(Haskell and SML are more clear about this; they use type for type synonyms and data (Haskell)/datatype(SML) to define new algebraic data types.)
An algebraic data type does not necessarily need to have more than one alternative. It is syntactically valid to do
type 'a entry = Value of string * 'a * 'a entry
However, in this case, this is probably not useful, because, how could it end?

Abstracting over Collection Types

Is there a possibility of writing functions which are generic in respect to collection types they support other than using the seq module?
The goal is, not having to resort to copy and paste when adding new collection functions.
Generic programming with collections can be handled the same way generic programming is done in general: Using generics.
let f (map_fun : ('T1 -> 'T2) -> 'T1s -> 'T2s) (iter_fun : ('T2 -> unit) -> 'T2s -> unit) (ts : 'T1s) (g : 'T1 -> 'T2) (h : 'T2 -> unit)=
ts
|> map_fun g
|> iter_fun h
type A =
static member F(ts, g, h) = f (Array.map) (Array.iter) ts g h
static member F(ts, g, h) = f (List.map) (List.iter) ts g h
A bit ugly and verbose, but it's possible. I'm using a class and static members to take advantage of overloading. In your code, you can just use A.F and the correct specialization will be called.
For a prettier solution, see https://stackoverflow.com/questions/979084/what-features-would-you-add-remove-or-change-in-f/987569#987569 Although this feature is enabled only for the core library, it should not be a problem to modify the compiler to allow it in your code. That's possible because the source code of the compiler is open.
The seq<'T> type is the primary way of writing computations that work for any collections in F#. There are a few ways you can work with the type:
You can use functions from the Seq module (such as Seq.filter, Seq.windowed etc.)
You can use sequence comprehensions (e.g. seq { for x in col -> x * 2 })
You can use the underlying (imperative) IEnumerator<'T> type, which is sometimes needed e.g. if you want to implement your own zipping of collections (this is returned by calling GetEnumerator)
This is relatively simple type and it can be used only for reading data from collections. As the result, you'll always get a value of type seq<'T> which is essentially a lazy sequence.
F# doesn't have any mechanism for transforming collections (e.g. generic function taking collection C to collection C with new values) or any mechanism for creating collections (which is available in Haskell or Scala).
In most of the practical cases, I don't find that a problem - most of the work can be done using seq<'T> and when you need a specialized collection (e.g. array for performance), you typically need a slightly different implementation anyway.

Resources