I am attempting to make a function such that it outputs a list that removes adjacent duplicates
let rec rem_adj_duplicates l =
let rec utn l n = match l with
[] -> n
| (x :: y :: xs) -> if (x != y) then utn (y::xs) (n::x)
else utn (y::xs) n
in utn l []
I get the following error:
Error: This expression has type 'a list
but an expression was expected of type 'a
The type variable 'a occurs inside 'a list
Why does n want to be type 'a instead of 'a list?
You have this:
if (x != y) then
utn (y::xs) (n::x)
else
utn (y::xs) n
In the first call you have n :: x, which says that x is a list and n is a non-list. Furthermore it says that the second argument to utn is a list. In the next call you have just n, which must be of the same type as the other call. Thus, n shows up as both a list and a non-list.
Possibly you wanted to have x :: n rather than n :: x?
Update
You say you're not allowed to use the # operator. This is actually reasonable, as using it in the way you wanted is not a good way to solve the problem. (Adding things one at a time to the end of a list is slow, i.e., quadratic time in the length of the list.)
I may be giving away too much, but a common way to solve this problem is to build the list in reverse order and reverse it at the end. This takes only linear time.
Related
I'm working on a problem where they ask us to write a function to determine if a matrix is square (n by n, for any n >= 0) with OCaml
I have a type matrix already defined
type matrix = float list list
Also I previously have a function that works to determine the length of a list
let rec length (l : 'a list): int =
match l with
| [] -> 0
| _ :: xs' -> 1 + length xs'
Right now I'm thinking about writing a helper function which checks if the length of all rows are equal
let rec check_row_equal (m : matrix): bool =
match m with
| [] -> true
| h1 :: h2 :: t ->
if length h1 <> length h2 then false
else check_row_equal (h2 :: t)
But when I ran this function in utop, it says Match_failure ("//toplevel//", 2, 2). If I have this helper function running correctly, my thought for my next function would be
let rec is_square (m : matrix): bool =
let l = length m in
if check_row_equal m == false then false
else if (l != the length of one of the rows) then false
else true
I haven't figured out how to calculate the length of the row, maybe another helper function like
let row_length (m : matrix): int =
match m with
| [] -> 0
| h :: t -> length h
But again, I need help with the check_row_equal function, please help me to fix that, thank u!
let rec check_row_equal (m : matrix): bool =
match m with
| [] -> true
| h1 :: h2 :: t ->
if length h1 <> length h2 then false
else check_row_equal (h2 :: t)
You're getting a match error because you have a case for an empty list, and a list with two or more elements, but not a list with one element. Presumably if there is only one row, this should return true.
Incorporating this and simplifying the code a bit.
let rec check_row_equal (m : matrix): bool =
match m with
| [] | [_] -> true
| h1 :: (h2 :: _ as tl) ->
length h1 = length h2 && check_row_equal tl
You don't say what it means specifically to check whether a matrix is square. I'll assume you want to check the lengths of all the contained lists to make sure they're the same, and this should also be the same as the length of the outer list.
Here are a couple of comments:
Your length function works correctly in the abstract, but it doesn't work for the normal kind of OCaml list. In OCaml, the empty list (the final tail of every list) looks like [] and Cons (a, b) looks like a :: b. Maybe your code is supposed to work with a custom list type, but then it's confusing to name it list, like the normal OCaml list.
You already have a function length that visits every element of a list and calculates an answer. You need a function just like this except that each element of the list is another list, and you want to determine whether the lengths of these are all the same. Just as your length function gets a new result by adding 1 to the returned result, you can figure out an operation that tracks whether the lists have all been the same length so far and, if so, what that length was.
I hope this helps. I don't want to write code for you because this is an assignment.
I'm still trying to understand how fold_left exactly works. Does it iterate through the list like List.iter? Or is there just something else wrong with my code? I'm thinking that e is the element in the list (so it's a tuple) and fst e takes the first element of the tuple and snd e takes the second element in the tuple.
let rec pow x n =
if n < 0 then
0
else if n = 0 then
1
else
x * pow x (n - 1);;
let polynomial lst = function
| x -> List.fold_left (fun e -> (fst e) * (pow x (snd e))) 1 lst;;
lst is a list of tuples where each tuple has two integers and makes a polynomial function, so polynomial is supposed to return a function. So an example of what should happen is this
# let f = polynomial [3, 3; -2, 1; 5, 0];;
val f : int -> int = <fun>
# f 2;; (* f is the polynomial function f(x) = 3x^3 + (-2)x + 5 *)
- : int = 25
But I get this error message
"Error: This expression has type int but an expression was expected of type 'a -> int * int".
List.fold_left indeed iterates over a list, passing the value from one call to another, which basically works like a bucket brigade, with only one bucket, where on each iteration you can look into the bucket, take whatever is there and put something new.
More formally, fold_left f init elements has type
val fold_left : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a
and it takes three arguments, the function f, the initial value init, and a list of elements. The function f is called for each element x of elements as f acc x, where acc is either init if x is the first element of the list or a result returned by the previous invocation of f. Back to our analogy, it is either the initial empty bucket or a bucket passed from the previous call in the chain.
In your case, the role of the bucket is the final sum of all terms. Initially, it is empty, then each new term computes (fst e) * (pow x (snd e)) and adds it to the bucket so that at the end you will have the sum of all terms,
let polynomial coeffs x =
List.fold_left (fun sum (k,r) -> sum + k * pow x r) 0 coeffs
Note, that instead of using fst and snd to access the elements of the pair, I deconstructed the tuple directly in the parameter list. This makes code easier to understand and shorter.
The function, that is applied on each step takes two arguments, sum is the bucket (it is often called the "accumulator") and the element of the list, which is a pair (k,r) in our case. We multiply k by the value of the x variable raised to the power r and then we add the result to the accumulator.
For people with an imperative mindset the following pseudocode1 might be more insightful than the bucket brigade analogy:
def fold_left(user_func, init, elements):
acc = init
for elt in elts:
acc = user_func(acc, elt)
return acc
1) Any resemblance to Python is purely coincidental :)
I need to implement a method to return common elements in two lists as part of an assignment problem:
My idea was to remove duplicates in both lists, concatenate them and return elements that are repeated in the resulting list. I want to define a Boolean function that check for each elements in the list if they appear more than once. My idea was to use List.fold_left with a specific element b in the list and use acc to keep track of the number of times it appears in the list. However, I have an error here:
I have another idea that involves sorting the lists first, But the list could be of any type, hence comparison has to be implemented for new types as well. Or can I just use < to compare any type of values?
Here are the codes that I have so far.
let rec remove (b : 'a) (l : 'a list)=
match l with
| [] -> []
| w::e -> if w=b then remove b e
else w::(remove b e)
let rec removeduplicates (l:'a list)=
match l with
| [] -> []
| w::e -> w::(removeduplicates(remove w e))
let removeduppair (l : 'a list * 'a list)=
let (l1,l2) = l in
(removeduplicates l1, removeduplicates l2)
This expression has a type error:
if x = b then acc + 1
The problem is that doesn't have an else part. In other words, it doesn't say what you want the value to be when x is not equal to b.
You can fix this just by adding an else part.
A little more detail: OCaml allows you to leave off the else part, but only if the then part has unit type. In such a case, the value when the test is false will be the same as when it is true, namely () (the only value of unit type).
Batteries.LazyList allows one to define lazy lists. I would like to define a lazy list consisting of x, f x, f (f x), f (f (f x)), etc.
Based on comments in the module documentation, it appears that from_loop is the function I want:
"from_loop data next creates a (possibly infinite) lazy list from the successive results of applying next to data, then to the result, etc."
This description suggests that if I wanted a lazy list of non-negative integers, for example, I could define it like this:
let nat_nums = from_loop 0 (fun n -> n + 1)
However, this fails because the signature of from_loop is
'b -> ('b -> 'a * 'b) -> 'a LazyList.t
so the next function has signature ('b -> 'a * 'b). In utop, the error message underlines n + 1 and says
Error: This expression has type int but an expression was expected of type 'a * int
I don't understand what 'a is supposed to be. Why is the next function supposed to return a pair? Why is the type of the list supposed to be a 'a LazyList.t? Shouldn't the type of the elements be the same as the type of the argument to the next function? The description of the function doesn't make the answers clear to me.
In case it's helpful, my conception of what I'm trying to do comes from Clojure's iterate. In Clojure I could create the above definition like this:
(def nat-nums (iterate (fn [n] (+ n 1)) 0))
The function passed to from_loop has to return a pair. The first element of the pair is the value you want to return. The second element of the pair is the state required to calculate the next element later on.
Your code:
(fun n -> n + 1)
Just calculates the next element of the lazy list, it doesn't return the state required for the next call. Something like this is what is wanted:
(fun n -> (n, n + 1))
(This will return a list starting with 0, which I think is what you want.)
This formulation is more flexible than your clojure example, because it allows you to maintain arbitrary state distinct from the values returned. The state is of type 'b in the type you give for from_loop.
I don't have Batteries right now, so I can't try this out. But I think it's correct based on the types.
It turns out that the function that I really wanted was LazyList.seq, not from_loop. While from_loop has its uses, seq is simpler and does what I wanted. The only trick is that you have to provide a third argument which is a termination test that returns false when the list should end. I wanted an infinite list. One can create that using use a termination function that always returns true:
let nat_nums = seq 0 (fun n -> n + 1) (fun _ -> true);;
LazyList.to_list (LazyList.take 8 nat_nums);;
- : int list = [0; 1; 2; 3; 4; 5; 6; 7]
I am new to OCaml and I am trying to write a function to do this:
(4,a)(1,b)(2,c)(2,a)(1,d)(4,e) --> ((4 a) b (2 c) (2 a) d (4 e))
and this is what I wrote:
let rec transform l =
match l with
| (x,y)::t -> if x = 1 then y::transform(t) else [x; y]::transform(t)
| [] -> []
I put it in the ocaml interpreter but error generated like this:
Error: This expression has type int list
but an expression was expected of type int
Could anyone give some help?
Your example transformation doesn't make it clear what the types of the values are supposed to be.
If they're supposed to be lists, the result isn't a possible list in OCaml. OCaml lists are homogeneous, i.e., all the elements of the list have the same type. This is (in essence) what the compiler is complaining about.
Update
Looking at your code, the problem is here:
if x = 1
then y :: transform (t)
else [x; y] :: transform t
Let's say the type of y is 'a. The expression after then seems to have type 'a list, because y is the head of the list. The expression after else seems to have type 'a list list, because a list containing y is the head of the list. These aren't the same type.
The main problem is to decide how to represent something as either (4 a) or b. The usual OCaml way to represent something-or-something-else is variants, so let's define one of those:
type 'a element =
| Single of 'a
| Count of int * 'a
let rec transform = function
| [] -> []
| (x,y)::t ->
if x = 1 then Single y::transform t
else Count (x, y)::transform t
Note that this won't print in quite the way you want, unless you register a printer with the toplevel.
Or better:
let compact (x, y) =
if x = 1 then Single y else Count (x, y)
let transform list = List.map compact list