Ocaml use match with lazylist - ocaml

I am trying to fill ma lazylist by unpaired elements (with recursion), starting with element k. For example: k = 2, list is [2,3,5,7,9,...] The code:
let lgen =
let rec gen k = LCons(k, fun () -> gen k (k + 2))
in gen 1;;
But how can I check is the element k unpaired? (I think that here I need to use match).

Assuming your type for lazy lists is something like this:
type 'a llist = LNil | LCons of 'a * (unit -> 'a llist);;
You can pattern match like this:
let rec lfind e lxs =
match lxs with
| LNil -> false
| LCons(x, _) when x > e -> false
| LCons(x, xs) -> if e=x then true else lfind e (xs ())
;;

Related

This expression has type 'a list -> 'a list but an expression was expected of type int

let rec first_part n l =
if n = 0 then
[]
else
match l with
| [] -> []
| x :: xs -> x :: first_part n-1 xs
let rec second_part n l =
match l with
| [] -> []
| x :: xs ->
if n = 0 then l
else second_part n-1 xs
let rec split n l =
match n with
| 0-> ([], l)
| n -> (first_part n l , second_part n l)
This isn't a very well posed question. You don't show the details of the error or ask a specific question. You also didn't format the code in a readable way (I improved it for you).
Your problem is that
first_part n-1 xs
is parsed like this
(first_part n) - (1 xs)
Function calls in OCaml (juxtaposed expressions) have high precedence. So you need parentheses around (n - 1) in two places.

OCaml Recursive function : sublist elements multiplied by their position in a list and then summed

I’m trying to create a function that takes an int list as an argument and returns the sum of the product between an int and its position in the list. To put in an example this : multSum [5; 11; 15] should return (5 * 1 + 11 * 2 + 15 * 3) = 72.
It should be written recursively and I’m trying while avoiding List.map or List.filter or any other prefabricated functions.
By dividing and reigning the query above, I have so far started by trying the following :
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t ;;
val tir : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
then I moved to this :
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto";;
val carto : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
with the final idea to be able to do that :
let prod arg1 arg2 =
tir (+) 1 (carto ( * ) arg1 arg2);;
val prod : int list -> int list -> int = <fun>
But I am stuck now and I’m not sure of my orientation from here forward. I thought of trying to search for the index in a "l" and replace each index int in the acc, in order to make it work but I'm afraid I'm rather complicating things... Any help please ?
Edit 1 :
let rec multSum l =
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t)in
let rec tir f acc l =
match l with
|[] -> acc
|h::t -> tir f (f acc h) t in
let rec carto f a b =
match (a,b) with
|([],[])->([])
|(h1::t1,h2::t2)->(f h1 h2):: (carto f t1 t2)
|_->invalid_arg "carto" in
let prod arg1 arg2 =
tir (+) 0 (carto ( * ) arg1 arg2) in
prod l (indices 1 l);;
val multSum : int list -> int = <fun>
Building on your replies, surely these are 'fold' and 'map' rewritten. At least, I'm sure now that I was on the right track. I have come to put together the whole code as signaled above in Edit 1.
It seems to be working well... I know that I want a recursive function and here it is. But, do you think it could be done even shorter recursively of course?
#coredump is quite right about this looking like an ideal scenario for a fold, but the extra functions aren't really that necessary. We can just use a tuple to pass the index and sum information around, then when we're done, discard the index information from the tuple.
let sum_list_prod lst =
let (_, result) = List.fold_left
(fun (i, sum) x -> (i + 1, sum + i * x))
(1, 0)
lst
in
result
Edit: A simple implementation of a left fold to demonstrate the recursion going on here.
let rec foldl f init lst =
match lst with
| [] -> init
| first :: rest -> foldl f (f init first) rest
So working through a simple example with sum_list_prod:
sum_list_prod [2; 3; 4]
Calls the fold like so:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
And as that evaluates:
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (1, 0) [2; 3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (2, 2) [3; 4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (3, 8) [4]
List.fold_left (fun (i, sum) x -> (i + 1, sum + i * x)) (4, 20) []
(4, 20)
And then we throw away the 4 because we don't need it anymore and are just left with 20.
Your tir functions looks like a fold; in fact has the exact same type as List.fold_left:
# List.fold_left;;
- : ('a -> 'b -> 'a) -> 'a -> 'b list -> 'a = <fun>
In the following snippets the prod function looks like a map2
# List.map2;;
- : ('a -> 'b -> 'c) -> 'a list -> 'b list -> 'c list = <fun>
You can use a fold and a map to compute the function you want, but you also need first to build a list of indices from the list of values. You could do this as follows:
let rec indices n xs = match xs with
| [] -> []
| h::t -> n::(indices (n+1) t);;
For example:
# indices 1 [5;1;3];;
- : int list = [1; 2; 3]
This is not recursive terminal, if you first computed the length of the list, how would you build the list in a recursive terminal way?
Then you should be able to call prod on a list xs and on a secondary list indices 1 xs. It is a bit wasteful because you need to build an auxiliary list, but it looks quite simple to me to understand, higher-order functions like map or fold do work on whole lists so there are fewer corner cases to consider.
But, it might be better to first write a direct recursive function for your particular problem before going the more abstract route.
The direct recursive function also requires no additional memory allocation. If you write a recursive terminal function you'll carry additional accumulator values:
the current position in the list, initially 1
the current sum of products, initially 0
Then, your function has the following skeleton:
let rec f xs index product = match xs with
| [] -> ...
| h::t -> ...
You can wrap it in a main function g:
let g xs = f xs 1 0;;

Delete elements between two occurrences in list

I have to make a function that take a list and return the list but without the elements betweens the occurences.
For example: [1; 2; 3; 4; 2; 7; 14; 21; 7; 5] -> [1; 2; 7; 5]
I imagined that to make this I will take the head of the list, and then see
if there is another occurrence in the tail, so I browse the list and when I found the occurrence, I delete everything between them and I keep just one of them.
First I tried something like this:
let rec remove list = match list with
| [] -> []
| h::t -> if(List.mem h t) then
(*Here I would like to go through the list element by element to
find the occurence and then delete everything between*)
else
remove t
So for the part I don't succeed to do, I made a function which allows to slice a list between two given points, just like so:
let slice list i k =
let rec take n = function
| [] -> []
| h :: t -> if n = 0 then [] else h :: take (n-1) t
in
let rec drop n = function
| [] -> []
| h :: t as l -> if n = 0 then l else drop (n-1) t
in
take (k - i + 1) (drop i list);;
(*Use: slice ["a";"b";"c";"d";"e";"f";"g";"h";"i";"j"] 2 3;;*)
I also have this function that allows me to get the index of points in the list:
let index_of e l =
let rec index_rec i = function
| [] -> raise Not_found
| hd::tl -> if hd = e then i else index_rec (i+1) tl
in
index_rec 0 l ;;
(*Use: index_of 5 [1;2;3;4;5;6] -> return 4*)
But I don't really know how to combine them to get what I expect.
here is what I made :
let rec remove liste =
let rec aux l el = match l with
| [] -> raise Not_found
| x :: xs -> if el = x then try aux xs el with Not_found -> xs
else aux xs el in
match liste with
| [] -> []
| x :: xs -> try let r = x :: aux xs x in remove r with Not_found -> x :: remove xs;;
my aux function return the list which follow the last occurence of el in l. If you have any question or if you need more explanation just ask me in comment
A version that uses an option type to tell if an element appears further on in the list:
let rec find_tail ?(eq = (=)) lst elem =
match lst with
| x :: _ when eq x elem -> Some lst
| _ :: xs -> find_tail ~eq xs elem
| [] -> None
let rec remove ?(eq = (=)) lst =
match lst with
| [x] -> [x]
| x :: xs -> begin
match find_tail ~eq xs x with
| Some tail -> x :: remove ~eq (List.tl tail)
| None -> x :: remove ~eq xs
end
| [] -> []
Also lets you specify a comparison function (Defaulting to =).

Why this program dosen't halt when only need to iterating throught a finite stream?

I'm trying to get a list of primes of two digits by running these codes in LearnOcaml. The codes compile if I restrict the parameter of the listify method, which returns a list from a stream, to be less than 20. Otherwise, it either never halt or return "Exception: Js_of_ocaml__Js.Error _.". I don't think the code is semantically wrong. So I'm
wondering if anyone can help resolve the problem?
type 'a stream = Eos | StrCons of 'a*(unit -> 'a stream)
(*integers from n onwards*)
let rec nums_from n =
StrCons(n,fun () -> nums_from (n+1))
let rec filterStr (test : 'a -> bool) (s: 'a stream) =
match s with
|Eos -> Eos
|StrCons(q,w) -> if test q then StrCons(q,fun ()-> filterStr test (w ()))
else filterStr test (w ())
(*Remove all numbers mod p*)
let sift p =
filterStr (fun x -> x mod p <> 0)
(*Sieves*)
let rec sieves s =
match s with
|Eos ->Eos
|StrCons(x,g) -> StrCons(x, fun ()-> sieves (sift x (g ())))
(*primes*)
let allprimes = sieves (nums_from 2)
let rec listify s n=
if n =0 then [] else
match s with
|Eos -> []
|StrCons(q,w) -> q::(listify (w ()) (n-1))
let twodigitsprimes = filterStr (fun x -> x > 10&& x<100) allprimes
let twodigitsprimeslist= listify twodigitsprimes 21
It appears that filterStr is looping while trying to create the StrCons that represents the next element after the 21st. Since there are only 21 2-digit primes, this will loop forever.
Note that when listify is called with n = 0, the StrCons has already been constructed; it just isn't examined. But the StrCons for this case diverges (and OCaml is a strict language).
You can get things to work using this version of listify:
let rec listify s n =
if n = 0 then []
else
match s with
| Eos -> []
| StrCons (q, w) ->
if n = 1 then [q] else q :: listify (w ()) (n - 1)

Represent a nil list and/or a list(nil)

Background
We are implementing this algorithm in F#.
Here is a little bit more information from Topor (1982) about the notation that the algorithm uses:
Formally, a 't list is either null (denoted nil) or has a hd (which is a 't) and a tl (which is a 't list)... If x is a list, we test whether it is null by writing null x... We create a new list, adding the element a at the front of an existing list x, by writing a:x... We denote the unit list containing the element a by list(a)... list(x) = x:nil.
Question
What we're wondering is how in F# to express those nil, null, and list(nil) values. For instance, should we be using the Option type, an empty list, or something else?
What We Have Tried
let rec kpermute k (xs: 't list) =
let rec mapPerm k xs ys =
match ys with
| [] -> []
| head::tail ->
let kpermuteNext = kpermute (k-1) (removeFirst head xs)
let mapPermNext = mapPerm k xs tail
mapcons head kpermuteNext mapPermNext
match k with
| 0 -> [[]]
| _ when xs.Length < k -> []
| _ -> mapPerm k xs xs
When working with lists, for list(nil) we use [[]] and for nil we use []. While that's fine, there might be a more expressive way to do it. There are also times when we use List.empty<'t list> and List.empty<'t> when the type inference needs more information.
The paper gives you all the answers: nil is []; null x is a test for whether x is the empty list; list(nil) is [[]].
The naïve translation of algorithm B to F# is as follows:
let rec minus a = function
| [] -> failwith "empty list"
| xh :: xt -> if xh = a then xt else xh :: minus a xt
let rec permute2 k x =
if k = 0 then [[]]
elif List.length x < k then []
else mapperm k x x
and mapperm k x = function
| [] -> []
| yh :: yt -> mapcons yh (permute2 (minus yh x)) (mapperm x yt)
and mapcons a ps qs =
match ps with
| [] -> qs
| ph :: pt -> a :: ph :: mapcons a pt qs