Trying to implement boolean disjunction on list using List.fold_right - ocaml

I am trying to implement boolean disjunction. I have successfully implemented it using recursion, and for a bit of practice I am trying to do the same using List.fold_right but I am failing miserably.
let q1fold lst =
List.fold_right (fun lst acc ->
match lst with
| [] -> acc
| h::t -> if h then true else false )

Consider the type signature of List.fold_right:
# List.fold_right;;
- : ('a -> 'b -> 'b) -> 'a list -> 'b -> 'b = <fun>
Three arguments are taken. You've only passed one.
List.fold_right and List.fold_left consider an initial value and each element of the input list and runs a function on them to generate the initial value for the next iteration, returning that value at the end of the list.
What do you think the "update" and the initial values should be in the following to implement the functionality you want?
List.fold_right (fun x init -> ...) [true; false; false] ...
Note 1: I would use List.fold_left as it is tail-recursive, though for a small dataset it is unlikely to make a practical difference here.
Note 2: if h then true else false is equivalent to h.

Related

List.assoc using List.find

I want to implement the List.assoc function using List.find, this is what I have tried:
let rec assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> try (List.find (fun x -> a = x) lista)
b
with Not_found -> assoc l x;;
but it gives me this error:
This expression has type ('a * 'b) list but an expression was expected of type 'a list
The type variable 'a occurs inside 'a * 'b
I don't know if this is something expected to happen or if I'm doing something wrong. I also tried this as an alternative:
let assoc lista x = match lista with
| [] -> raise Not_found
| (a,b)::l -> match List.split lista with
| (l1,l2) -> let ind = find l1 (List.find (fun s -> compare a x = 0))
in List.nth l2 ind;;
where find is a function that returns the index of the element requested:
let rec find lst x =
match lst with
| [] -> raise Not_found
| h :: t -> if x = h then 0 else 1 + find t x;;
with this code the problem is that the function should have type ('a * 'b) list -> 'a -> 'b, but instead it's (('a list -> 'a) * 'b) list -> ('a list -> 'a) -> 'b, so when I try
assoc [(1,a);(2,b);(3,c)] 2;;
I get:
This expression has type int but an expression was expected of type
'a list -> 'a (refering to the first element of the pair inside the list)
I don't understand why I don't get the expected function type.
First off, a quick suggestion on making your assoc function more idiomatic OCaml: have it take the list as the last argument.
Secondly, why are you attempting to implement this in terms of find? It's much easier without.
let rec assoc x lista =
match lista with
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
Something like this is simpler and substantially more efficient with the way lists work in OCaml.
Having the list as the last argument, even means we can write this more tersely.
let rec assoc x =
function
| [] -> raise Not_found
| (a, b) :: xs -> if a = x then b else assoc x xs
As to your question, OCaml infers the types of functions from how they're used.
find l1 (List.find (fun s -> compare a x = 0))
We know l1 is an int list. So we must be trying to find it in an int list list. So:
List.find (fun s -> compare a x = 0)
Must return an int list list. It's a mess. Try rethinking your function and you'll end up with something much easier to reason about.

Filtering integers from list of list in OCaml

I am trying to write a function that filters positive integers from a list of list of integers, returning a list of only negative integers.
For example, if I have a list of list such as [[-1; 1]; [1]; [-1;-1]] it would return [[-1]; []; [-1;-1]].
I tried to use filter and transform functions, which was in my textbook.
let rec transform (f:'a -> 'b) (l:'a list) : 'b list =
begin match l with
| [] -> []
| x::tl -> (f x)::(transform f tl)
end
and for filter, I had previously written:
let rec filter (pred: 'a -> bool) (l: 'a list) : 'a list =
begin match l with
| [] -> []
| x :: tl -> if pred x then x :: (filter pred tl) else filter pred tl
end
So, using these, I wrote
let filter_negatives (l: int list list) : int list list =
transform (fun l -> (filter(fun i -> i<0)) + l) [] l
but I'm still having trouble fully understanding anonymous functions, and I'm getting error messages which I don't know what to make of.
This function has type ('a -> 'b) -> 'a list -> 'b list
It is applied to too many arguments; maybe you forgot a `;'.
(For what it's worth this transform function is more commonly called map.)
The error message is telling you a simple, true fact. The transform function takes two arguments: a function and a list. You're giving it 3 arguments. So something must be wrong.
The transformation you want to happen to each element of the list is a filtering. So, if you remove the + (which really doesn't make any sense) from your transforming function you have something very close to what you want.
Possibly you just need to remove the [] from the arguments of transform. It's not clear (to me) why it's there.

rev function of n-dimensional lists

I'm trying to make a function that take some list of type 'a list, where 'a could be of type 'b list, and 'b could be of type 'c list and so forth. it should revert every list in the list so that if 'a is a list then 'a should also be reverted and so forth.
let RevAll xs =
let rec rev acc = function
| (_::_)::__ as M -> rev ((rev List.Empty List.head M)::acc) (List.tail M)
| x::xs -> rev (x::acc) xs
| [] -> acc
rev List.Empty xs
Vs' compiler can't determent the types so it don't work. My question is as follow. Is there a way to make a function in F# that take an n-dimensional list and revert every dimension in that list without specifying the dimension?

SML/NJ return even integers from int list with foldr

I'm using SML recently and I'm trying to solve a problem.
I should create a function that accept an int list and return even int list,
I've already created it :
fun evens [] = [] |
evens [x] = [x] |
evens(x::xs) =
case x mod 2 of
0 => x::evens xs |
1 => evens xs;
which gives the correct result but I need to use foldr
this is what I came up with:
fun evens [] = [] |
evens(x::xs) =
case x mod 2 of
0 => foldr (op ::) evens xs [x] |
1 => evens xs;
but it is not working, I'm still confused with how to use foldr in this case.
any advice?
First of all, with foldr you should be looking for a 1-line definition rather than a recursive definition using patterns and cases. The point of foldr is that it incorporates a common recursion pattern -- you just need to use the pattern.
The type of foldr is
fn : ('a * 'b -> 'b) -> 'b -> 'a list -> 'b
In your case 'b is int list and 'a is int. The 'b between the arrows in the middle of foldr's type is the seed value. It typically corresponds to a basis value. When you are constructing lists this basis value is typically []. Thus -- you need to concentrate on the key question of what should be folded over the list. In other words -- what function of type ('a * 'b -> 'b) should you pass to foldr? In your case you need to pass a function of type
int * int list -> int list
this should be a function which, when given an int and an int list either tacks the int onto the list (if it is even) or leaves the list alone. You could define this function ahead of time, define it using let, or just use an anonymous function.
Under the assumption that this is homework, I don't want to give a complete answer, but here is a function which uses foldr to obtain the positive entries in a list:
fun positives xs =
foldr (fn (x,xs) => if x >= 0 then x::xs else xs) [] xs;
-
- positives [3,~2,4,5,0,~1,~1,5];
val it = [3,4,5,0,5] : int list

Ocaml - parameter type when checking for duplicates in a list

I've got a basic function which checks a list for duplicates and returns true if they are found, false otherwise.
# let rec check_dup l = match l with
[] -> false
| (h::t) ->
let x = (List.filter h t) in
if (x == []) then
check_dup t
else
true
;;
Yet when I try to use this code I get the error
Characters 92-93:
let x = (List.filter h t) in
^
Error: This expression has type ('a -> bool) list
but an expression was expected of type 'a list
I don't really understand why this is happening, where is the a->bool list type coming from?
The type ('a -> bool) list is coming from the type of filter and from the pattern match h::t in combination. You're asking to use a single element of the list, h, as a predicate to be applied to every element of the list t. The ML type system cannot express this situation. filter expects two arguments, one of some type 'a -> bool where 'a is unknown, and a second argument of type 'a list, where 'a is the same unknown type as in the first argument. So h must have type 'a -> bool and t must have type 'a list.
But you have also written h::t, which means that there is another unknown type 'b such that h has type 'b and t has type 'b list. Put this together and you get this set of equations:
'a -> bool == 'b
'a list == 'b list
The type checker looks at this and decides maybe 'a == 'b, yielding the simpler problem
'a -> bool == 'a
and it can't find any solution, so it bleats.
Neither the simpler form nor the original equation has a solution.
You are probably looking for List.filter (fun x -> x = h) t, and you would probably be even better off using List.exists.
For complete this answer I post the final function for search duplicate value in array:
let lstOne = [1;5;4;3;10;9;5;5;4];;
let lstTwo = [1;5;4;3;10];;
let rec check_dup l = match l with
[] -> false
| (h::t) ->
let x = (List.filter (fun x -> x = h) t) in
if (x == []) then
check_dup t
else
true;;
and when the function run:
# check_dup lstOne
- : bool = true
# check_dup lstTwo
- : bool = false
#