I was tasked with writing OCAML code to calculate the Trace of a square matrix (the values inside the diagonal of a matrix). As a bonus, and for my own understanding, I'd also like to write code to produce a list of the trace of a square matrix.
I've created a tail recursive function utilizing the List.map feature which strips the first element of each row, and so on and so forth.
let trace m =
let rec helper m acc =
match m with
|[] -> acc
|(x::_) -> helper(List.map(fun(y::ys) -> ys)) (acc+x)
in helper m 0 ;;
Unfortunately I believe my syntax is off and I am unsure how to go about solving this. I think I have the right theory/idea in mind but poor implementation. Any help would be greatly appreciated
This is the error I get when I run the code:
This expression has type 'a list list -> 'a list list but an expression was expected of type 'b list
1:Warning 8: this pattern-matching is not exhaustive.
Here is an example of a case that is not matched:
[]
As #glennsl says, you should do the work to ask a good question. You don't tell us anything about the error you see, for example. Generally you should copy/paste the error text into your question.
When I copy/paste your code I see an error for this fragment:
(List.map (fun (y :: ys) -> ys))
List.map takes two parameters: the first is a function, which you have. The second is a list to map over, which you don't have here. Since you don't supply a list, the value of this expression is a function that expects a list and returns the transformed list.
Since the first parameter of helper is a list of lists (I assume), and not a function, you have a type error. (Not a syntax error.)
Most likely you need to supply the list over which you want to map your function.
Related
Using only recursion (ie. no loops of any sort), given a list of elements, how can I call a function each time for every element of the list using that element as an argument each time in OCaml? Fold and map would not work because although they are applying a function to each element, it returns a list of whatever function I called on each element, which is not what I want.
To better illustrate what I'm essentially trying to do in OCaml, here's the idea of what I want in Ruby code:
arr.each {|x| some_function x}
but I must do this using only recursion and no iter functions
The correct recursive function is described as:
if the list is empty, do nothing;
else, process the first element and then the tail of the list.
The corresponding code is:
let rec do_all f lst =
match lst with
| [] -> ()
| x :: xs -> f x; do_all f xs
A fairly general template for a recursive function would be this:
let rec f x =
if x is trival to handle then
handle x
else
let (part, rest) = division of x into smaller parts in
let part_result = handle_part part in
let recursive_result = f rest in
combine part_result recursive_result
Since you don't need a result, you can skip a lot of this.
Which parts of this template seem most difficult to do for your problem?
Update
(As #EduardoLeón points out, when working with lists you can test for a trivial list and break down the list into smaller parts using pattern matching. Pattern matching is cool.)
Update 2
My question is sincere. Which part are you having trouble with? Otherwise we don't know what to suggest.
I am trying to recursively find the nth element in a list in ocaml using the following code.
let rec get_val x n = match x with
[] -> -1
| h::t -> if (n=0) then h else get_val t (n-1)
;;
print_int get_val [1; 2; 3] 1;;
However this code is giving me the error
This function has type int -> unit
It is applied to too many arguments; maybe you forgot a `;'.
Your definition is asking for two separate parameters (i.e., it is curried). But you're passing a pair of parameters (t, n - 1). These aren't the same thing.
To get past this problem, change the recursive call to get_val t (n - 1).
You might consider raising the Not_found exception when the list is too short. That way your code will work for lists of all types.
Update
Now the error is in the line where you test your function. You need parentheses there as well.
(You shouldn't keep changing your code. People who come to this page later won't be able to follow the questions and answers.)
So I have a function like so
let test (item: 'a ) (factors: items) : ('b list) =
....
This function takes in an item of some 'a elements and my own items type, which is another list of items I pass to it. I return a list of a different type later after doing some stuff
How do I use List.fold_left with this function so that if I have a list of 'a items, I can just apply test to each one individually, and pass 'factors' to all of them, and then so that I can concatenate the resultant 'b type lists for each one.
For example, the I would need to process the following list:
[somea; someb; somec]
as
(test somea factors)#(test someb factors)#(test somec factors)
Is this a task that List.fold_left is not applicable for? Is there some other function I can use? I can't recursively traverse and call the function because of some mutually-recursive problems going on with the other methods in my code so is there another way? Would List.map be useful here instead?
For this particular purpose, things would go better if factors was the first parameter of test. Let's call this function fliptest:
let fliptest a b = test b a
So then your function looks like this (it seems to me):
let process factors list =
List.concat (List.map (fliptest factors) list)
(If this isn't quite right, it's probably close.)
Suppose I've got the sequence <1,<>,2,<>>.
How could I go about deleting the empty lists and get <1,2>?
Ideally, without using recursion or iteration.
Thanks.
PS: I'm using FP programming language
What you're probably looking for is filter. It takes a predicate and takes out elements not satisfying it.
Since the FP language has a weird syntax and I couldn't find any documentation , I can't provide an implementation of filter. But in general, it can be implemented using a fold -- which is just the inserts from the link you provided.
Here's what I mean (in Haskell):
filter p list = foldr (\x xs -> if p x then x:xs else xs) [] list¹
If you don't get this, look here. When you have written filter, you can call it like
newList = filter notEmpty theList
(where nonEmpty is a predicate or lambda). Oh, and of course this only hides recursion by using another function; at some point, you have to recurse.
¹The : operator in Haskell is list consing (appending an element to the head), not function application.
I wrote a function which generates a list of randomized ints in OCaml.
let create_shuffled_int_list n =
Random.self_init;
let rec create n' acc =
if n' = 0 then acc
else
create (n'-1) (acc # [Random.int (n/2)])
in
create n [];;
When I tried to generate 10000 integers, it gives Exception: RangeError: Maximum call stack size exceeded. error.
However, I believed in the function, I have used tail-recursion and it should not give stackoverflow error, right?
Any idea?
From the core library documentation
val append : 'a list -> 'a list -> 'a list
Catenate two lists. Same function as the infix operator #. Not tail-recursive (length of the first argument). The # operator is not tail-recursive either.
So it's not your function that's causing the overflow, it's the # function. Seeing as you only care about producing a shuffled list, however, there's no reason to be appending things onto the end of lists. Even if the # operator were tail-recursive, list append is still O(n). List prepending, however, is O(1). So if you stick your new random numbers on the front of your list, you avoid the overflow (and make your function much much faster):
let create_shuffled_int_list n =
Random.self_init;
let rec create n' acc =
if n' = 0 then acc
else
create (n'-1) (Random.int (n/2) :: acc)
in
create n [];;
If you care about the order (not sure why), then just stick a List.rev on the end:
List.rev (create n []);;
As an aside, you should not call Random.self_init in a function, since:
the user of your function may want to control the seed in order to obtain reproductible results (testing, sharing results...)
this may reset the seed with a not so random entropy source and you probably want to do this only once.