I am trying to iterate through a stream in order to print the content.
type 'a stream = Nil | Cons of 'a * 'a stream thunk and 'a thunk = unit -> 'a
This is where my function is called
|> iter_stream ~f:(fun (f,c,l) -> printf "%s %s %s\n" f c l)
And this is the type
let rec iter_stream st ~f
(* val iter_stream : 'a stream -> ('a -> unit) -> unit *)
I can't seem to find any examples on how to implement it. The only idea I have is to think about it like a list which is obviously wrong since I get type errors.
let rec iter_stream st ~f =
match st with
| None -> ()
| Some(x, st') -> f x; iter_stream st' ~f
Your stream is extremely similar to a list, except that you need to call a function to get the tail of the list.
Your proposed code has many flaws. The main two flaws that I see are:
You're using the constructors None and Some while a stream has constructors Nil and Cons.
You're not calling a function to get the tail of the stream. Note that in Cons (a, b), b is a "stream thunk", i.e., it's a function that you can call to get a stream.
(Perhaps these are the only two flaws :-)
I hope this helps.
Related
I have a function f: 'a -> Async<'b option> that I want to call with 'a option instead of 'a. Now, if I had a function g that returned Async<'b> instead of f's Async<'b option>, I could write a standard traverse implementation and I would then have Async<'b option> at the end. But if I use traverse with f, the result is Async<'b option option>.
It seems to me I need something like this:
module Option =
let traverseBindAsync (f: 'a -> Async<'b option>) (opt: 'a option) : Async<'b option> =
async {
match opt with
| None -> return None
| Some x -> return! f x
}
I don't think traverseBind is a recognized concept (no search results). Is it known under another name, or alternatively, is there another way to think about this in terms of recognized FP concepts one can express in F#? If so, could I use those concepts in a way that is more or less as syntactically concise as the above Option.traverseBindAsync?
I'm not aware of any standard name for a function of a type like this. However, there are two changes you can do to the code that might be somewhat revealing. First, you can implement it without the use of the async block, just by using either f x or by returning async.Unit(None), i.e. an asynchronous computation that immediately returns None:
let traverseBindAsync (f: 'a -> Async<'b option>) (opt: 'a option) : Async<'b option> =
match opt with
| None -> async.Return None
| Some x -> f x
Now you can also rewrite this as doing Option.map on the input and using async.Return(None) as the default value when the input option (and therefore also the result of the map operation) is None:
let traverseBindAsync (f: 'a -> Async<'b option>) (opt: 'a option) : Async<'b option> =
opt |> Option.map f |> Option.defaultValue (async.Return None)
I don't think this has any name, but you can think of your function as Option.map with a particular default value when the input is not available.
I am actually sitting over a hour on a problem and donĀ“t find a solution for it.
I have this data type:
type 'a tree = Empty | Node of 'a * 'a tree * 'a tree
And i have to find a function which converts a given tree in a ordered list. There is also no invariant like that the left child has to be less then the right. I already found a "normal" recursion solution but not a tail recursive solution. I already thought about to build a unordered list and sort it with List.sort, but this uses a merge sort which is not tail recursive. Maybe someone has a good advice.
Thank you!
If you want to traverse the tree in order and return a list, that means our function inorder must have the type 'a tree -> 'a list.
let rec inorder t =
match t with
| Empty -> []
| Node (v, l, r) -> List.append (inorder l) (v :: (inorder r)) (* ! *)
However List.append is in tail position, not inorder. Another problem is we have two calls to inorder. If we put inorder l in tail position, inorder r could not possibly be in tail position - and vice versa.
A neat way to work around this problem is continuation passing style. We take our function above and convert it into a helper function with an extra parameter for our continuation, return
(* convert to helper function, add an extra parameter *)
let rec loop t return =
match t with
| Empty -> ...
| Node (v, l, r) -> ...
The continuation represents "what to do next", so instead of sending values directly out of our function, we must hand them to the continuation instead. That means for the Empty case, we'll return [] - instead of simply []
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) -> ...
For the Node (v, l, r) case, now that we have an extra parameter we can write our own continuation that informs loop what to do next. So to construct our sorted list, we will need to loop l, then loop r (or vice versa), then we can append them. We'll write our program just like this.
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop l ... (* build the left_result *)
loop r ... (* build the right_result *)
return (List.append left_result (v :: right_result))
In this next step, we'll fill in the actual lambda syntax for the continuations.
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop l (fun left ->
loop r (fun right ->
return (List.append left (v :: right))))
Last, we define inorder which is a call to loop with the default continuation, identity.
let identity x =
x
let inorder t =
let rec loop t return =
match t with
| Empty -> return []
| Node (v, l, r) ->
loop r (fun right ->
loop l (fun left ->
return (List.append left (v :: right))))
in
loop t identity
As you can see loop r (fun right -> ...) is in tail position for the Node branch. loop l (fun left -> ...) is in tail position of the first continuation. And List.append ... is in tail position of the second continuation. Provided List.append is a tail-recursive procedure, inorder will not grow the stack.
Note using List.append could be a costly choice for big trees. Our function calls it once per Node. Can you think of a way to avoid it? This exercise is left for the reader.
I was reading about continuations in Standard ML (SMLofNJ.Cont). I understood what callcc and throw does, but could not understand isolate. The documentation says
Discard all live data from the calling context (except what is reachable from f or x), then call f(x), then exit. This may use much less memory then something like f(x) before exit().
However this does not make any sense to me. I just wanted to know what this function does, with some examples.
MLton does a better job of explaining an implementation of isolate using callcc and throw:
val isolate: ('a -> unit) -> 'a t =
fn (f: 'a -> unit) =>
callcc
(fn k1 =>
let
val x = callcc (fn k2 => throw (k1, k2))
val _ = (f x ; Exit.topLevelSuffix ())
handle exn => MLtonExn.topLevelHandler exn
in
raise Fail "MLton.Cont.isolate: return from (wrapped) func"
end)
We use the standard nested callcc trick to return a continuation that is ready to receive an argument, execute the isolated function, and exit the program. [...]
The page continues to explain how to achieve the same effect with less space leaking.
MLton's CONT signature has a different documentation line than SML/NJ's CONT signature:
isolate f creates a continuation that evaluates f in an empty context.
This is a constant time operation, and yields a constant size stack.
In a learning environment, what are my options to provide type signatures for functions?
Standard ML doesn't have top-level type signatures like Haskell. Here are the alternatives I have considered:
Module signatures, which require either a separate signature file, or the type signature being defined in a separate block inside the same file as the module itself. This requires the use of modules, and in any production system that would be a sane choice.
Modules may seem a little verbose in a stub file when the alternative is a single function definition. They both introduce the concept of modules, perhaps a bit early,
Using val and val rec I can have the complete type signature in one line:
val incr : int -> int =
fn i => i + 1
val rec map : ('a -> 'b) -> 'a list -> 'b list =
fn f => fn xs => case xs of
[] => []
| x::ys => f x :: map f ys
Can I have this and also use fun?
If this is possible, I can't seem to get the syntax right.
Currently the solution is to embed the argument types and the result type as such:
fun map (f : 'a -> 'b) (xs : 'a list) : 'b list =
raise Fail "'map' is not implemented"
But I have experienced that this syntax gives the novice ML programmer the impression that the solution either cannot or should not be updated to the model solution:
fun map f [] = []
| map f (x::xs) = f x :: map f xs
It seems then that the type signatures, which are supposed to aid the student, prevents them from pattern matching. I cannot say if this is because they think that the type signatures cannot be removed or if they should not be removed. It is, of course, a matter of style whether they should (and where), but the student should be enabled to explore a style of type inference.
By using a let or local bound function, and shadowing
you can declare the function, and then assign it to a value.
using local for this is more convenient, since it has the form:
local decl in decl end, rather than let decl in expr end,
meaning let's expr, wants a top-level argument f
val map = fn f => let fun map = ... in map end
I don't believe people generally use local, anymore primarily because modules can do anything that local can, and more, but perhaps it is worth considering it as an anonymous module, when you do not want to explain modules yet.
local
fun map (f : 'a -> 'b) (x::rest : 'a list) : 'b list
= f x :: map f rest
| map _ ([]) = []
in
val (map : ('a -> 'b) -> 'a list -> 'b list) = map;
end
Then when it comes time to explain modules, you can declare the structure inside the local, around all of the declarations,
and then remove the local, and try to come up with a situation, where they have coded 2 functions, and it's more appropriate to replace 2 locals, with 1 structure.
local
structure X = struct
fun id x = x
end
in val id = X.id
end
perhaps starting them off with something like the following:
exception ReplaceSorryWithYourAnswer
fun sorry () = raise ReplaceSorryWithYourAnswer
local
(* Please fill in the _'s with the arguments
and the call to sorry() with your answer *)
fun map _ _ = sorry ()
in
val map : ('a -> 'b) -> ('a list) -> ('b list) = map
end
I've started learning F# and I'd like to write my own map function using tail-recursion. Here is what I have
let my_map ff list =
let rec mapAcc ff_inner list_inner acc =
match list_inner with
| [] -> acc
| front::rest -> mapAcc( ff_inner rest (ff_inner(front) :: acc) ) //error
mapAcc ff list []
It would be called like this:
let list = my_map (fun x -> x * 2) [1;2;3;4;5] // expect [2;4;6;8;10]
I get an compilation error message on the second condition that says Type mismatch. Expecting a 'a but given a 'b list -> 'a -> 'a The resulting type would be infinite when unifying ''a' and ''b list -> 'a -> 'a'
I don't know what this error message means. I'm not sure how this can be infinite if I am passing the rest in the recursive call to mapAcc.
Note: I realize I'm rebuilding the list backwards. I'm ignoring that for now.
Just remove the parenthesis when the function calls itself:
let my_map ff list =
let rec mapAcc ff_inner list_inner acc =
match list_inner with
| [] -> acc
| front::rest -> mapAcc ff_inner rest (ff_inner(front) :: acc)
mapAcc ff list []
otherwise everything contained there is interpreted as a single parameter and ff_inner as a function call with the rest as parameters.