Having trouble with a problem:
Define a function called zip that takes a pair (tuple) of equal length lists as a single parameter and returns a list of pairs. The first pair should contain the first element of each list, the second pair contains the second element of each list, and so on.
I have been stuck and am looking for advice on if I'm headed in the right direction or should try another approach.
It needs to be a single function definition without any nested functions and can not use build in functions!
What I have done is:
let rec zip (a , b) =
if List.length a = 1 then List.head a , List.head b
else zip (List.tail a , List.tail b)
when
> zip (["a"; "b"; "c"; "d"; "e"], [1; 2; 3; 4; 5]);;
is entered
val it : string * int = ("e", 5)
is returned.
The expected result should be
val it : (string * int) list = [("a", 1); ("b", 2); ("c", 3); ("d", 4); ("e", 5)]
Let's start with your original implementation:
let rec zip (a , b) =
if List.length a = 1 then List.head a , List.head b
else zip (List.tail a , List.tail b)
First of all, the type is wrong - this returns a tuple of values, not a list of tuples. What this does is that it iterates over the list (following the tails using List.tail) and when it reaches the end, it returns the only element of each of the lists, which is "e" and 5.
The first step to fixing this could be to add type annotations. This will force you to return a list in the then branch. If you have two singleton lists ["e"] and [5], you want to return ["e", 5]:
let rec zip (a:'a list , b:'b list) : list<'a * 'b> =
if List.length a = 1 then [List.head a , List.head b]
else zip (List.tail a , List.tail b)
This is still not right - in the else case, you are just looking at the tails, but you are ignoring the heads. You need to access the head and concatenate it to the list returned from your recursive call:
let rec zip (a:'a list , b:'b list) : list<'a * 'b> =
if List.length a = 1 then [List.head a , List.head b]
else (List.head a, List.head b) :: zip (List.tail a , List.tail b)
This works, but using if .. then .. else in this case is inelegant. The answer from Filipe shows how to do this better with pattern matching.
let rec zip (a, b) =
match (a, b) with
| ha :: ta, hb :: tb -> (ha, hb) :: zip (ta, tb)
| _, _ -> []
Related
I am a new at F# and i try to do this task:
Make a function compare : string list -> string list -> int that takes two string lists and returns: -1, 0 or 1
Please help. I spend a lot of time, and i can not understand how to implement this task.
Given the task I assume what your professor wants to teach you with this exercise. I'll try to give you a starting point without
Confusing you
Presenting a 'done-deal' solution
I assume the goal of this task is to work with recursive functions and pattern matching to element-wise compare their elements. It could looks somewhat like this here
open System
let aList = [ "Apple"; "Banana"; "Coconut" ]
let bList = [ "Apple"; "Banana"; "Coconut" ]
let cList = [ "Apple"; "Zebra" ]
let rec doSomething f (a : string list) (b : string list) =
match (a, b) with
| ([], []) ->
printfn "Both are empty"
| (x::xs, []) ->
printfn "A has elements (we can unpack the first element as x and the rest as xs) and B is empty"
| ([], x::xs) ->
printfn "A is empty and B has elements (we can unpack the first element as x and the rest as xs)"
| (x::xs, y::ys) ->
f x y
printfn "Both A and B have elements. We can unpack them as the first elements x and y and their respective tails xs and ys"
doSomething f xs ys
let isItTheSame (a : string) (b : string) =
if String.Equals(a, b) then
printfn "%s is equals to %s" a b
else
printfn "%s is not equals to %s" a b
doSomething isItTheSame aList bList
doSomething isItTheSame aList cList
The example has three different lists, two of them being equal and one of them being different. The doSomething function takes a function (string -> string -> unit) and two lists of strings.
Within the function you see a pattern match as well as a recursive call of doSomething in the last match block. The signatures aren't exactly what you need and you might want to think about how to change the parametrization for cases where you don't want to stop the recursion (the last match block - if the strings are equal you want to keep on comparing, right?).
Just take the code and try it out in FSI. I'm confident, that you'll find the solution 🙂
In F# many collections are comparable if their element type is:
let s1 = [ "a"; "b" ]
let s2 = [ "foo"; "bar" ]
compare s1 s2 // -5
let f1 = [ (fun () -> 1); fun () -> 2 ]
let f2 = [ (fun () -> 3); fun () -> 42 ]
// compare f1 f2 (* error FS0001: The type '(unit -> int)' does not support the 'comparison' constraint. *)
so
let slcomp (s1 : string list) s2 = compare s1 s2 |> sign
Posting for reference as the original question is answered already.
I have to create a type tree which would be used to store words, like every node of the tree would hold a letter and the list of the next characters (so words with the same root would share the same "part/branch of the tree). the tree is basically a n-ary one, used as a dictionnary.
All using Caml language
Well, I don't know if it's a homework or not but I'll still answer :
First, we need to define a signature type for letters.
module type LS = sig
type t
val compare : t -> t -> int
end
Then, we need to define our structure :
module Make (L : LS) = struct
module M = Map.Make(L)
type elt = L.t list
type t = { word : bool; branches : t M.t }
let empty = { word = false; branches = M.empty }
let is_empty t = not t.word && M.is_empty t.branches
let rec mem x t =
match x with
| [] -> t.word
| c :: cl -> try mem cl (M.find c t.branches)
with Not_found -> false
let rec add x t =
match x with
| [] -> if t.word then t else { t with word = true }
| c :: cl ->
let b = try M.find c t.branches with Not_found -> empty in
{ t with branches = M.add c (add cl b) t.branches }
end
Now, step by step :
module Make (L : LS) = struct is a functor that will return a new module if we give it a module of type LS as an argument
module M = Map.Make(L)
type elt = L.t list
type t = { word : bool; branches : t M.t }
This is the complex point, once you have it, everything begins clear. We need to represent a node (as you can see in the Wikipedia page of tries). My representation is this : a node is
a truth value stating that this node represent a word (which means that all the letters from the root to this node form a word)
the branches that goes from it. To represent this branches, I need a dictionary and luckily there's a Map functor in OCaml. So, my field branches is a field associating to some letters a trie (which is why I wrote that branches : t M.t). An element is then a list of letters and you'll find out why I chose this type rather than a string.
let empty = { word = false; branches = M.empty } the empty trie is the record with no branches (so, just the root), and this root is not a word (so word = false) (same idea for is_empty)
let rec mem x t =
match x with
| [] -> t.word
| c :: cl -> try mem cl (M.find c t.branches)
with Not_found -> false
Here it becomes interesting. My word being a list of letters, if I want to know if a word is in my trie, I need to make a recursive functions going through this list.
If I reached the point where my list is empty it means that I reached a node where the path from the root to it is composed by all the letters of my word. I just need to know, then, if the value word at this node is true or false.
If I still have at least one letter I need to find the branch corresponding to this letter.
If I find this branch (which will be a trie), I just need to make a recursive call to find the rest of the word (cl) in it
If I don't find it I know that my word doesn't exist in my trie so I can return false.
let rec add x t =
match x with
| [] -> if t.word then t else { t with word = true }
| c :: cl ->
let b = try M.find c t.branches with Not_found -> empty in
{ t with branches = M.add c (add cl b) t.branches }
Same idea. If I want to add a word :
If my list is empty it means that I added all the letters and I've reached the node corresponding to my word. In that case, if word is already true it means that this word was already added, I don't do anything. If word is false I just return the same branch (trie) but with word equal to true.
If my list contains at least a letter c, I find in the current node the branch corresponding to it (try M.find c t.branches with Not_found -> empty) and I there's no such branch, I just return an empty one and then I recursively add the rest of my letters to this branch and add this new branch to the branches of my current node associated to the letter c (if this branch already existed, it will be replaced since I use a dictionary)
Here, we start with the empty trie and we add the word to, top and tea.
In case we don't want to use functors, we can do it this way :
type elt = char list
type t = { word : bool; branches : (char * t) list }
let empty = { word = false; branches = [] }
let is_empty t = not t.word && t.branches = []
let find c l =
let rec aux = function
| [] -> raise Not_found
| (c', t) :: tl when c' = c -> t
| _ :: tl -> aux tl
in aux l
let rec mem x t =
match x with
| [] -> t.word
| c :: cl -> try mem cl (find c t.branches)
with Not_found -> false
let rec add x t =
match x with
| [] -> if t.word then t else { t with word = true }
| c :: cl ->
let b = try find c t.branches with Not_found -> empty in
{ t with branches = (c, (add cl b)) :: t.branches }
I'm building a merge sort function and my split method is giving me a value restriction error. I'm using 2 accumulating parameters, the 2 lists resulting from the split, that I package into a tuple in the end for the return. However I'm getting a value restriction error and I can't figure out what the problem is. Does anyone have any ideas?
let split lst =
let a = []
let b = []
let ctr = 0
let rec helper (lst,l1,l2,ctr) =
match lst with
| [] -> []
| x::xs -> if ctr%2 = 0 then helper(xs, x::l1, l2, ctr+1)
else
helper(xs, l1, x::l2, ctr+1)
helper (lst, a, b, ctr)
(a,b)
Any input is appreciated.
The code, as you have written it, doesn't really make sense. F# uses immutable values by default, therefore your function, as it's currently written, can be simplified to this:
let split lst =
let a = []
let b = []
(a,b)
This is probably not what you want. In fact, due to immutable bindings, there is no value in predeclaring a, b and ctr.
Here is a recursive function that will do the trick:
let split lst =
let rec helper lst l1 l2 ctr =
match lst with
| [] -> l1, l2 // return accumulated lists
| x::xs ->
if ctr%2 = 0 then
helper xs (x::l1) l2 (ctr+1) // prepend x to list 1 and increment
else
helper xs l1 (x::l2) (ctr+1) // prepend x to list 2 and increment
helper lst [] [] 0
Instead of using a recursive function, you could also solve this problem using List.fold, fold is a higher order function which generalises the accumulation process that we described explicitly in the recursive function above.
This approach is a bit more concise but very likely less familiar to someone new to functional programming, so I've tried to describe this process in more detail.
let split2 lst =
/// Take a running total of each list and a index*value and return a new
/// pair of lists with the supplied value prepended to the correct list
let splitFolder (l1, l2) (i, x) =
match i % 2 = 0 with
|true -> x :: l1, l2 // return list 1 with x prepended and list2
|false -> l1, x :: l2 // return list 1 and list 2 with x prepended
lst
|> List.mapi (fun i x -> i, x) // map list of values to list of index*values
|> List.fold (splitFolder) ([],[]) // fold over the list using the splitFolder function
I wrote a recursive version of index as follows
let index list value =
let rec counter num = function
| [] -> -1
| h::t ->
if h == value
then num
else (counter (num + 1)) t
in counter 0 list;;
It works, but then our professor said we should use a tail recursive version in order to not timeout on the server, so I wrote a new index function using fold, but I can't seem to figure out why if it doesn't find the element, it returns a number greater than the length of the list, even though I want it to return -1.
let index2 list value = fold (fun i v ->
if i > (length list) then -1
else if v == value then i
else i+1) 0 list;;
Here's my fold version as well:
let rec fold f a l = match l with
[] -> a
| (h::t) -> fold f (f a h) t;;
Your folded function is called once for each element of the list. So you'll never see a value of i that's greater than (length list - 1).
As a side comment, it's quite inefficient (quadratic complexity) to keep calculating the length of the list. It would be better to calculate it once at the beginning.
As another side comment, you almost never want to use the == operator. Use the = operator instead.
EDIT
Why do you redefine fold instead of using List.fold_left?
Your first version of index is already tail recursive, but you can improve its style by:
using option type instead of returning -1 if not found;
directly call index recursively instead of a count function;
use = (structural) comparator instead of == (physical);
use a guard in your pattern matching instead of an if statement.
So
let index list value =
let rec index' list value i = match list with
| [] -> None
| h :: _ when h = value -> Some i
| _ :: t -> index' t value (succ i)
in index' list value 0
And as already said, index2 does not work because you'll never reach an element whose index is greater than the length of the list, so you just have to replace i > (length list) with i = (length list) - 1 to make it work.
But index2 is less efficient than index because index stops as soon as the element is found whereas index2 always evaluate each element of the list and compare the list length to the counter each time.
I have a tiny grammar represented as a variant type term with strings that are tokens/part of tokens (type term).
Given expressions from the grammar, I am collecting all strings from expressions and pack them into sets (function vars). Finally, I want to create some graph with these sets as vertices (lines 48-49).
For some reason, the graph created in the such sophisticated way does not recognise sets containing same variables and creates multiple vertices with the same content. I don't really understand why this is happening.
Here is minimal working example with this behaviour:
(* demo.ml *)
type term =
| Var of string
| List of term list * string option
| Tuple of term list
module SSet = Set.Make(
struct
let compare = String.compare
type t = string
end)
let rec vars = function
| Var v -> SSet.singleton v
| List (x, tail) ->
let tl = match tail with
| None -> SSet.empty
| Some var -> SSet.singleton var in
SSet.union tl (List.fold_left SSet.union SSet.empty (List.map vars x))
| Tuple x -> List.fold_left SSet.union SSet.empty (List.map vars x)
module Node = struct
type t = SSet.t
let compare = SSet.compare
let equal = SSet.equal
let hash = Hashtbl.hash
end
module G = Graph.Imperative.Digraph.ConcreteBidirectional(Node)
(* dot output for the graph for illustration purposes *)
module Dot = Graph.Graphviz.Dot(struct
include G
let edge_attributes _ = []
let default_edge_attributes _ = []
let get_subgraph _ = None
let vertex_attributes _ = []
let vertex_name v = Printf.sprintf "{%s}" (String.concat ", " (SSet.elements v))
let default_vertex_attributes _ = []
let graph_attributes _ = []
end)
let _ =
(* creation of two terms *)
let a, b = List ([Var "a"], Some "b"), Tuple [Var "a"; Var "b"] in
(* get strings from terms packed into sets *)
let avars, bvars = vars a, vars b in
let g = G.create () in
G.add_edge g avars bvars;
Printf.printf "The content is the same: [%s] [%s]\n"
(String.concat ", " (SSet.elements avars))
(String.concat ", " (SSet.elements bvars));
Printf.printf "compare/equal output: %d %b\n"
(SSet.compare avars bvars)
(SSet.equal avars bvars);
Printf.printf "Hash values are different: %d %d\n"
(Hashtbl.hash avars) (Hashtbl.hash bvars);
Dot.fprint_graph Format.str_formatter g;
Printf.printf "Graph representation:\n%s" (Format.flush_str_formatter ())
In order to compile, type ocamlc -c -I +ocamlgraph demo.ml; ocamlc -I +ocamlgraph graph.cma demo.cmo. When the program is executed you get this output:
The content is the same: [a, b] [a, b]
compare/equal output: 0 true
Hash values are different: 814436103 1017954833
Graph representation:
digraph G {
{a, b};
{a, b};
{a, b} -> {a, b};
{a, b} -> {a, b};
}
To sum up, I am curious why there are non-equal hash values for sets and two identical vertices are created in the graph, despite the fact these sets are equal by all other means.
I suspect the general answer is that OCaml's built-in hashing is based on rather physical properties of a value, while set equality is a more abstract notion. If you represent sets as ordered binary trees, there are many trees that represent the same set (as is well known). These will be equal as sets but might very well hash to different values.
If you want hashing to work for sets, you might have to supply your own function.
As Jeffrey pointed out, it seems that the problem is in the definition of the hash function that is part of Node module.
Changing it to let hash x = Hashtbl.hash (SSet.elements x) fixed the issue.