So I'm writing a combining function for fold that will make it perform filtering.
let filter_combine (pred: 'a -> bool) : a' list -> 'a list -> 'a list =
fun (x: 'a) (y: 'a list) -> x :: (filter pred y)
I am not having any compilation issues, but one out of my two test cases is failing. What is wrong with my implementation?
This is the test case that fails...
[-1; 1] = fold (filter_combine (fun (x: int) -> (abs x) mod 2 <> 0)) [] [-2; -1; 0; 1; 2]
This is the one that works...
[-2; 2] = fold (filter_combine (fun (x: int) -> (abs x) > 1)) [] [-2; -1; 0; 1; 2]
I'm having some trouble understanding this question. I think what you're saying is that you want to write a function that takes a predicate and returns a function suitable for use with a fold so that the result will filter according to the predicate.
Some problems with the question:
There's no built-in OCaml function named fold.
If you're supposed to implement filtering, it seems fairly weird to use filter in your implementation.
If I assume you're using fold_right, then it seems to me you'd want to return a function of type a -> a list -> a list. It wants to look at one thing to decide what to do, not at a whole list of things. Since you say you're not getting compilation errors, this suggests that your function named fold doesn't work as I would expect. It might help if you showed how fold actually works.
Related
I know List.map uses recursion, I'm just wondering if there's a simpler way to implement map function without using recursion.
I know for reverse, I can simplify it into:
(* given *)
type 'a list =
| []
| (::) of 'a * 'a list
let nil : 'a list = []
let cons (hd : 'a) (tl : 'a list): 'a list = hd :: tl
let reverse (ls : 'a list): 'a list =
List.fold_left (Fun.flip cons) [] ls
Right now I'm thinking about using ##(the application operator), %(the function composition operator), and maybe Fun.flip or List.fold_left to do it, can anyone give me some hint about that?
I have tried the following, but OCaml raised an error about it.
List.fold_left (fun x -> f x) [] ls
List.fold_left uses recursion, so presumably you're looking to avoid use of the rec keyword, rather than recursion at all.
You note in comments trying:
List.fold_left (fun x -> f x) [] ls
But the function passed to List.fold_left must take two arguments: the initial state, and the first element of the list. Fun.flip cons worked in your reverse function because it does take two arguments.
Note: fun x -> f x is the same as writing f.
If you initial state is a list, you need to do something to that list in the function you pass to List.fold_left, like adding the result of f x to the front of it. Since this builds the list backwards, you will need to reverse the result. This is where ## will come in handy.
let map f lst =
List.(
rev ## fold_left (fun i x -> f x :: i) [] lst
)
I'm learning about the map and fold functions. I'm trying to write a function that takes a list and returns a list with all of the values in the original, each followed by that value's double.
Example: add_dbls [2;5;8] = [2;4;5;10;8;16]
Everything I try results in a list of lists, instead of a list. I'm struggling to come up with a better approach, using either map or fold (or both).
This is what I came up with originally. I understand why this returns a list of lists, but can't figure out how to fix it. Any ideas would be appreciated!
let add_dbls list =
match list with
| h::t -> map (fun a-> [a;(a*2)]) list
| [] -> []
Also, my map function:
let rec map f list =
match list with
| h::t -> (f h)::(map f t)
| [] -> []
You are nearly there. As you have observed, since we get list of lists, we need to flatten it to get a final list. List.concat function does exactly that:
let add_dbls list =
let l =
match list with
| h::t -> List.map (fun a -> [a;(a*2)]) list
| [] -> []
in
List.concat l
Here is the updated function that that computes the output that you require.
Now the output of add_dbls [2;5;8] = [2;4;5;10;8;16].
Although this works, it probably isn't efficient as it allocates a new list per item in your original list. Below are variations of the same function with different characteristics which depend on the size of l.
(* Safe version - no stack overflow exception. Less efficient(time and size) than add_dbls3 below. *)
let add_dbls2 l =
List.fold_left
(fun acc a -> (a*2)::a::acc)
[]
l
|> List.rev
(* Fastest but unsafe - stack overflow exception possible if 'l' is large - fold_right is not tail-recursive. *)
let add_dbls3 l =
List.fold_right
(fun a acc -> a::(a*2)::acc)
l
[]
It's should be simple to see that List.map always returns a list of the same length as the input list. But you want a list that's twice as long. So List.map cannot work for you.
You can solve this using List.fold_left or List.fold_right. If you're still having trouble after you switch to using a fold, you could update your question with the new information.
Update
The type of your fold function (a left fold) is this:
('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
So, the folded function takes an accumulated answer and an element of the list, and it returns a new accumulated answer.
Your folded function is like this:
fun a b -> a::b::(b*2)
It attempts to use the :: operator to add new elements to the end of the accumulated list. But that's not what the :: operator does. It adds an element to the beginning of a list.
There's no particularly nice way to add an element to the end of a list. This is intentional, because it's a slow operation.
When using a left fold, you need to reconcile yourself to building up the result in reverse order and possibly reversing it at the end. Or you can use a right fold (which is generally not tail recursive).
List.map is of type
- : ('a -> 'b) -> 'a list -> 'b list = <fun>
It's easy for me to understand the following code:
List.map (fun x -> x+1) [1;2;3;4];;
which adds 1 to each element of the list so it returns the following list :
- : int list = [2;3;4;5]
Now this is in an exercise where I'm asked to indicate the type of this :
List.map (fun p -> p 7) [ (fun n m -> n + m) ];;
I don't understand at all what it means to be honest.
What does p 7 mean ?
Why is there a function in the list ?
The type is
- : (int -> int) list = [<fun>]
But I can't understand why.
What does it mean when fun is between brackets ?
Thank you.
What does p 7 mean?
It means the application of function p to argument 7 .... You might spend some time reading the wikipage on λ-calculus (at least to learn about functional abstraction)
Read also about currying.
Why is there a function in the list ?
In Ocaml, functions are values, so you can have list of functions. If it was not a list of functions, you'll get a typing error. If you think more, you can understand what kind of functions are allowed.
What does it mean when fun is between brackets ?
The toplevel is not able to print functional values (implemented as closures). It shows them as <fun>. For a simpler example, pass fun x -> x+1;; (then try also fun y -> y;;) to your REPL.
(the rest of the exercise is left to the reader)
I've defined functions:
fun concaten(x,y) =
if (x = [])
then y
else hd(x) :: concaten(tl(x),y);
as well as:
fun existsin(x,L) =
if (L=[])
then false
else if (x = hd(L))
then true
else existsin(x,tl(L));
and am now trying to define a function of type (((list * list) -> list) -> list) that looks vaguely like the following:
fun strongunion(x,y) =
val xy = concaten(x,y);
if xy=[]
then []
if (existsin(hd(xy),tl(xy)) andalso x!= [])
then strongunion(tl(x),y)
else if (existsin(hd(xy),tl(xy)) andalso x = [])
then strongunion(x,tl(y))
else if (x != [])
then hd(xy) :: strongunion(tl(x),y)
else hd(xy) :: strongunion(x,tl(y));
which takes the "strong" union of two lists, i.e. it combats faulty inputs (lists with element duplicates). This code is, of course, syntactically invalid, but the reason I included it was to show what such a function would look like in an imperative language.
The way I started going about doing this was to first concatenate the lists, then remove duplicated elements from that concatenation (well, technically I am adding non-duplicates to an empty list, but these two operations are consequentially equivalent). To do this, I figured I would design the function to take two lists (type list*list), transform them into their concatenation (type list), then do the duplicate removal (type list), which would be of type (((list*list) -> list) -> list).
My issue is that I have no idea how to do this in SML. I'm required to use SML for a class for which I'm a TA, otherwise I wouldn't bother with it, and instead use something like Haskell. If someone can show me how to construct such higher-order functions, I should be able to take care of the rest, but I just haven't come across such constructions in my reading of SML literature.
I'm a bit unsure if strong union means anything other than just union. If you assume that a function union : ''a list * ''a list -> ''a list takes two lists of elements without duplicates as inputs, then you can make it produce the unions without duplicates by conditionally inserting each element from the one list into the other:
(* insert a single element into a list *)
fun insert (x, []) = [x]
| insert (x, xs as (y::ys)) =
if x = y
then xs
else y::insert(x, ys)
(* using manual recursion *)
fun union ([], ys) = ys
| union (x::xs, ys) = union (xs, insert (x, ys))
(* using higher-order list-combinator *)
fun union (xs, ys) = foldl insert ys xs
Trying this:
- val demo = union ([1,2,3,4], [3,4,5,6]);
> val demo = [3, 4, 5, 6, 1, 2] : int list
Note, however, that union wouldn't be a higher-order function, since it doesn't take functions as input or return functions. You could use a slightly stretched definition and make it curried, i.e. union : ''a list -> ''a list -> ''a list, and say that it's higher-order when partially applying it to only one list, e.g. like union [1,2,3]. It wouldn't even be fully polymorphic since it accepts only lists of types that can be compared (e.g. you can't take the union of two sets of functions).
I'm just starting out with F*, by which I mean I've written a few lines along with the tutorial. So far it's really interesting and I'd like to keep learning.
The first thing I tried to do on my own was to write a type that represents a non-empty list. This was my attempt:
type nonEmptyList 'a = l : (list 'a) { l <> [] }
But I get the error
Failed to verify implicit argument: Subtyping check failed; expected
type (a#6468:Type{(hasEq a#0)}); got type Type
I know I'm on the right track though because, if I constrain my list type to containing strings, this does work:
type nonEmptyList = l : (list string) { l <> [] }
I'm assuming this means that l <> [] in the original example isn't valid because I haven't specified that 'a should support equality. The problem is that I cannot for the life of me figure out how to do that. I guess is has something to do with a higher kind called hasEq, but trying things such as:
type nonEmptyList 'a = l : (list 'a) { hasEq 'a /\ l <> [] }
hasn't gotten me anywhere. The tutorial doesn't cover hasEq and I can't find anything helpful in the examples in the GitHub repo so now I'm stuck.
You correctly identified the problem here. The type 'a that you used in the definition of nonEmptyList is left unspecified and therefore could not support equality. Your intuition is correct, you need to tell F* that 'a is a type that has equality, by adding a refinement on it:
To do that, you can write the following:
type nonEmptyList (a:Type{hasEq a}) = l : (list a) { l <> [] }
Note that the binder I used for the type is a and not 'a. It would cause a syntax error, it makes more sense because it isn't "any" type anymore.
Also, note that you can be even more precise and specify the universe of the type a as Type0 if needbe.
Your analysis is indeed correct, and the accepted answer gives the right solution in general.
For your concrete example, though, you don't need decidable equality on list elements: you can just use (list 'a){ ~ (List.isEmpty l) }.
For reference, here's the definition of isEmpty:
(** [isEmpty l] returns [true] if and only if [l] is empty *)
val isEmpty: list 'a -> Tot bool
let isEmpty l = match l with
| [] -> true
| _ -> false