Adding lists as elements to make a list of list - list

For my assignment, I need to return a list of lists given a tree.
For example, given this tree, we return the paths of the leaves, 0 being going to the left and 1 being going to the right. At the current moment, I believe my function makes sense; however, I have no idea how to make the lists into a list of lists. I believe an operation needs to be put where the question mark is; however I've looked online and I could not find anything. Is there an operation for this? Or do I have to create my own helper function? Thank you.
let rec dTree_path t =
match t with
| Leaf(x) -> []
| Node(x, lt, rt) -> [ 0 :: (dTree_path lt) ] ?? [1 :: (dTree_path rt)];;
I

When doing exercices where function types are well specified, it can be useful to write the specification explicitely in order to make the typechecker report issues as soon as possible. In this case, adding a type annotation yields a compiler error on 0::dTree_path lt
let rec dTree_path: 'any t -> int list list = fun x ->
match x with
| Leaf(x) -> []
| Node(x, lt, rt) -> [ 0 :: (dTree_path lt) ] …;;
Error: This expression has type int list list
but an expression was expected of type int list
Type int list is not compatible with type int
And indeed, the current issue with your function is that 0 :: (dTree_path lt) does not make sense with respect to your specification: dTree_path is a list of lists of ints (i.e. a list of paths), but you are appending an int element to this list.
Hint: What you want to do is to append 0 to each path of the list of path returned by dTree_path.

Related

Using fold_left to search for a list with a specific length in OCaml

I've written a function which search through a list of int-list to return the index of the list with an specific length by using pattern-matching:
let rec search x lst i = match lst with
| [] -> raise(Failure "Not found")
| hd :: tl -> if (List.length hd = x) then i else search x tl (i+1)
;;
For example:
utop # search 2 [ [1;2];[1;2;3] ] 0 ;;
- : int = 0
Is there a way to write a function with the same functionality using fold.left ?
What does List.fold_left actually do?
It takes (in reverse order to the order of arguments) a list, an initial value, and a function that works on that initial value and the first element in the list. If the list is empty, it returns the initial value. Otherwise it uses the function to update the initial value by way of recursion and works on the tail of the list.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
Now, what information do you need to keep track of as you iterate? The index. Easy enough.
But, what if you don't actually find a list of that length? You need to keep track of whether you've found one. So let's say we use a tuple of the index and a boolean flag.
Your function you pass to fold_left just needs to determine if a match has been found no update is necessary. Essentially we just no-op over the rest of the list. But, if we haven't found a match, then we need to test the current sublist's length and update the init value accordingly.
#glennsl (in a comment) and #Chris already explained that you may use List.fold_left but that it’s not the right tool for the job, because it processes the whole list whereas you want to stop once an occurrence is found. There are solutions but they are not satisfying:
(#Chris’ solution:) use a folding function that ignores the new elements once an occurrence has been found: you’re just wasting time, walking through the remaining tail for nothing;
evade the loop by throwing and catching an exception: better but hacky, you’re working around the normal functioning of List.fold_left.
I just mention that there is a generic function in the standard library that matches your situation almost perfectly:
val find : ('a -> bool) -> 'a list -> 'a
find f l returns the first element of the list l that satisfies the predicate f.
Raises Not_found if there is no value that satisfies f in the list l.
However it does not return the index, unlike what you are asking for. This is a deliberate design choice in the standard library, because list indexing is inefficient (linear time) and you shouldn’t do it. If, after these cautionary words, you still want the index, it is easy to write a generic function find_with_index.
Another remark on your code: you can avoid computing the lengths of inner lists fully, thanks to the following standard function:
val compare_length_with : 'a list -> int -> int
Compare the length of a list to an integer. compare_length_with l len is equivalent to compare (length l) len, except that the computation stops after at most len iterations on the list.
Since 4.05.0
So instead of if List.length hd = x, you can do if List.compare_length_with hd x = 0.

F# function to split lists failing on empty list [duplicate]

I have a F# function:
let removeEven (listToGoUnder : _ list) =
let rec listRec list x =
match list with
| [] -> []
| head::tail when (x%2 = 0) -> head :: listRec (tail) (x+1)
| head::tail -> listRec (tail) (x+1)
listRec listToGoUnder 0
It removes all elements at an even index in a list.
It works if I give the list some imput, like removeEven ['1';'2';'3'] I get ['1';'3'] which I am supposed to. But when I insert a empty list as parameter, I get this error:
stdin(78,1): error FS0030: Value restriction. The value 'it' has been
inferred to have generic type
val it : '_a list Either define 'it' as a simple data term, make
it a function with explicit arguments or, if you do not intend for it
to be generic, add a type annotation.
Help, anybody?
The empty list ([]) is quite special; it can be a list of any type. Therefore, the compiler complains that you don't have a specific type for []. Adding type annotation on the argument helps to solve the problem:
let results = removeEven ([]: int list)
or more idiomatic type annotation as suggested by #kvb:
let results: int list = removeEven []
This is probably beyond the question, but your function should be named as removeOdd since indices often start from 0 and your function removes all elements with odd indices. Moreover, things are much more clear if you use pattern matching on first two elements of the list rather than keep a counter x for checking indices:
let rec removeOdd = function
| [] -> []
| [x] -> [x]
| x::_::xs -> x::removeOdd xs

nested lists in ocaml

I am new to Ocaml and have defined nested lists as follows:
type 'a node = Empty | One of 'a | Many of 'a node list
Now I want to define a wrapping function that wraps square brackets around the first order members of a nested list. For ex. wrap( Many [ one a; Many[ c; d]; one b; one e;] ) returns Many [Many[one a; Empty]; Many[Many[c;d]; Empty]; Many[b; Empty]; Many[e; Empty]].
Here's my code for the same:
let rec wrap list = function
Empty -> []
| Many[x; y] -> Many [ Many[x; Empty]; wrap y;];;
But I am getting an error in the last expression : This expression has the type 'a node but an expression was expected of the type 'b list. Please help.
Your two matches are not returning values of the same type. The first statement returns a b' list; the second statement returns an 'a node. To get past the type checker, you'll need to change the first statement to read as: Empty -> Empty.
A second issue (which you will run into next) is that your recursive call is not being fed a value of the correct type. wrap : 'a node -> 'a node, but y : 'a node list. One way to address this would be to replace the expression with wrap (Many y).
There will also be in issue in that your current function assumes the Many list only has two elements. I think what you want to do is Many (x::y). This matches x as the head of the list and y as the tail. However, you will then need a case to handle Many ([]) so as to avoid infinite recursion.
Finally, the overall form of your function strikes me as a bit unusual. I would replace function Empty -> ... with match list with | Empty -> ....

ocaml bubble sort

My basic idea is to implement a bubble sort of type ('a list -> 'a list). I use variables which are sorted and result. If I change some of elements in the list, sorted becomes 1. Otherwise, sorted remains 0. Result is one cycle of the comparison.
I think there is something wrong with my sorted variable. Can anyone figure out what the problem is?
let rec sort (l: int list) : int list =
let sorted=0 in
let result = match l with
| []->[]
| x::xs-> if xs=[] then x
else let y::ys = xs in
if x<y then x::sort(xs)
else let sorted=1 in
y::sort(x::ys)
in
if sorted=0 then result
else sort(result)
It seems to me you're trying to use sorted as a mutable variable. OCaml variables are immutable. Once you bind a variable to a value, the binding can't be changed. Each of your let sorted = statements defines a new variable named sorted. So your last test will always show sorted to be equal to 0. It is testing the first definition of sorted, which can never have any other value than 0.
As Jeffrey said, OCaml values are immutable. That is why your program does not work as expected.
But there are other problems with your code:
sorted should have type bool, not int. One the pros of OCaml is that it has a strong type system, so use it.
To deconstruct list, you should use pattern matching only if xs=[] then x else let y::ys = xs in is not not the good way of doing it (and OCaml should warn you that your pattern matching is not exhaustive). You should add other cases to your pattern matching instead.
Like this:
| [] -> []
| x::[] -> x
| x::y::ys -> ...

SML: How can I pass a function a list and return the list with all negative reals removed?

Here's what I've got so far...
fun positive l1 = positive(l1,[],[])
| positive (l1, p, n) =
if hd(l1) < 0
then positive(tl(l1), p, n # [hd(l1])
else if hd(l1) >= 0
then positive(tl(l1), p # [hd(l1)], n)
else if null (h1(l1))
then p
Yes, this is for my educational purposes. I'm taking an ML class in college and we had to write a program that would return the biggest integer in a list and I want to go above and beyond that to see if I can remove the positives from it as well.
Also, if possible, can anyone point me to a decent ML book or primer? Our class text doesn't explain things well at all.
You fail to mention that your code doesn't type.
Your first function clause just has the variable l1, which is used in the recursive. However here it is used as the first element of the triple, which is given as the argument. This doesn't really go hand in hand with the Hindley–Milner type system that SML uses. This is perhaps better seen by the following informal thoughts:
Lets start by assuming that l1 has the type 'a, and thus the function must take arguments of that type and return something unknown 'a -> .... However on the right hand side you create an argument (l1, [], []) which must have the type 'a * 'b list * 'c list. But since it is passed as an argument to the function, that must also mean that 'a is equal to 'a * 'b list * 'c list, which clearly is not the case.
Clearly this was not your original intent. It seems that your intent was to have a function that takes an list as argument, and then at the same time have a recursive helper function, which takes two extra accumulation arguments, namely a list of positive and negative numbers in the original list.
To do this, you at least need to give your helper function another name, such that its definition won't rebind the definition of the original function.
Then you have some options, as to which scope this helper function should be in. In general if it doesn't make any sense to be calling this helper function other than from the "main" function, then it should not be places in a scope outside the "main" function. This can be done using a let binding like this:
fun positive xs =
let
fun positive' ys p n = ...
in
positive' xs [] []
end
This way the helper function positives' can't be called outside of the positive function.
With this take care of there are some more issues with your original code.
Since you are only returning the list of positive integers, there is no need to keep track of the
negative ones.
You should be using pattern matching to decompose the list elements. This way you eliminate the
use of taking the head and tail of the list, and also the need to verify whether there actually is
a head and tail in the list.
fun foo [] = ... (* input list is empty *)
| foo (x::xs) = ... (* x is now the head, and xs is the tail *)
You should not use the append operator (#), whenever you can avoid it (which you always can).
The problem is that it has a terrible running time when you have a huge list on the left hand
side and a small list on the right hand side (which is often the case for the right hand side, as
it is mostly used to append a single element). Thus it should in general be considered bad
practice to use it.
However there exists a very simple solution to this, which is to always concatenate the element
in front of the list (constructing the list in reverse order), and then just reversing the list
when returning it as the last thing (making it in expected order):
fun foo [] acc = rev acc
| foo (x::xs) acc = foo xs (x::acc)
Given these small notes, we end up with a function that looks something like this
fun positive xs =
let
fun positive' [] p = rev p
| positive' (y::ys) p =
if y < 0 then
positive' ys p
else
positive' ys (y :: p)
in
positive' xs []
end
Have you learned about List.filter? It might be appropriate here - it takes a function (which is a predicate) of type 'a -> bool and a list of type 'a list, and returns a list consisting of only the elements for which the predicate evaluates to true. For example:
List.filter (fn x => Real.>= (x, 0.0)) [1.0, 4.5, ~3.4, 42.0, ~9.0]
Your existing code won't work because you're comparing to integers using the intversion of <. The code hd(l1) < 0 will work over a list of int, not a list of real. Numeric literals are not automatically coerced by Standard ML. One must explicitly write 0.0, and use Real.< (hd(l1), 0.0) for your test.
If you don't want to use filter from the standard library, you could consider how one might implement filter yourself. Here's one way:
fun filter f [] = []
| filter f (h::t) =
if f h
then h :: filter f t
else filter f t