Lets say that I would like to construct a list (L2) by appending elements of another list (L) one by one. The result should be exactly the same as the input.
This task is silly, but it'll help me understand how to recurse through a list and remove certain elements.
I have put together the following code:
create(L, L2) :- (\+ (L == []) -> L=[H|T], append([H], create(T, L2), L2);[]).
calling it by
create([1,2,3,4], L2)
returns
L2 = [1|create([2,3,4], **)\.
which is not a desired result.
You say that you want to understand how prolog works so I'll not give you a full solution but a hint.
Functions in prolog do not return values, they just create bindings.
When you say
append([H], create(T, L2), L2);[]).
you are trying to use a return value.
Try to have append create bindings that you use in the recursive call.
Related
I have a type intlist:
type intlist = Nil | Cons of int * intlist
and I'd now like to write a function that reverses the list. I have no real idea how to go about this. in class, our prof defined a function within a function, I believe, but I don't have the solution with me. How would one do this, simply? I would appreciate if we can keep the coding rather rudimentary, seeing as I'm relatively new to this.
So far, I only have
let reverse (l : intlist) : intlist =
match l with
Nil -> Nil
| Cons(a, Nil) -> Cons(a, Nil)
This is how I tend to create these kinds of functions, so I've written the trivial part (which granted, may not actually be what I need to start with). Any help is appreciated, thanks!
You indeed need a helper function, since for the reversing you need to build another list, so you need a function that will recurse into one list, while building another list, i.e., that has two arguments. In fact, this helper function is called rev_append and it is appending a reversed contents of one list to another. But let's try to make it using a helper function defined in the scope of the rev function:
let rev xs =
let rec loop xs ys = match xs with
| Nil -> ys
| Cons (x,xs) -> loop xs (Cons (x,ys)) in
loop xs Nil
So, to reverse a list we just take each element of a list and put it into another list. Since list behaves like a stack we are getting the reversed list for free. It is like Hanoi towers, when you pick elements from one list (tower) and put them to another, they will end up in a reversed order.
I'm working with a polymorphic binary search tree with the standard following type definition:
type tree =
Empty
| Node of int * tree * tree (*value, left sub tree, right sub tree*);;
I want to do an in order traversal of this tree and add the values to a list, let's say. I tried this:
let rec in_order tree =
match tree with
Empty -> []
| Node(v,l,r) -> let empty = [] in in_order r#empty;
v::empty;
in_order l#empty
;;
But it keeps returning an empty list every time. I don't see why it is doing that.
When you're working with recursion you need to always reason as follows:
How do I solve the easiest version of the problem?
Supposing I have a solution to an easier problem, how can I modify it to solve a harder problem?
You've done the first part correctly, but the second part is a mess.
Part of the problem is that you've not implemented the thing you said you want to implement. You said you want to do a traversal and add the values to a list. OK, so then the method should take a list somewhere -- the list you are adding to. But it doesn't. So let's suppose it does take such a parameter and see if that helps. Such a list is traditionally called an accumulator for reasons which will become obvious.
As always, get the signature right first:
let rec in_order tree accumulator =
OK, what's the easy solution? If the tree is empty then adding the tree contents to the accumulator is simply the identity:
match tree with
| Empty -> accumulator
Now, what's the recursive case? We suppose that we have a solution to some smaller problems. For instance, we have a solution to the problem of "add everything on one side to the accumulator with the value":
| Node (value, left, right) ->
let acc_with_right = in_order right accumulator in
let acc_with_value = value :: acc_with_right in
OK, we now have the accumulator with all the elements from one side added. We can then use that to add to it all the elements from the other side:
in_order left acc_with_value
And now we can make the whole thing implement the function you tried to write in the first place:
let in_order tree =
let rec aux tree accumulator =
match tree with
| Empty -> accumulator
| Node (value, left, right) ->
let acc_with_right = aux right accumulator in
let acc_with_value = value :: acc_with_right in
aux left acc_with_value in
aux tree []
And we're done.
Does that all make sense? You have to (1) actually implement the exact thing you say you're going to implement, (2) solve the base case, and (3) assume you can solve smaller problems and combine them into solutions to larger problems. That's the pattern you use for all recursive problem solving.
I think your problem boils down to this. The # operator returns a new list that is the concatenation of two other lists. It doesn't modify the other lists. In fact, nothing ever modifies a list in OCaml. Lists are immutable.
So, this expression:
r # empty
Has no effect on the value named empty. It will remain an empty list. In fact, the value empty can never be changed either. Variables in OCaml are also immutable.
You need to imagine constructing and returning your value without modifying lists or variables.
When you figure it out, it won't involve the ; operator. What this operator does is to evaluate two expressions (to the left and right), then return the value of the expression at the right. It doesn't combine values, it performs an action and discards its result. As such, it's not useful when working with lists. (It is used for imperative constructs, like printing values.)
If you thought about using # where you're now using ;, you'd be a lot closer to a solution.
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.
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'm trying to learn smlnj at the moment and am having trouble with a fold function.
What I'm trying to do is write a function, select, that uses the folding pattern and takes in a function and a list. It will take the head of the list into the function to determine whether it will add that element to the list. Here is an example of what I mean.
select (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
val it = [2,4,6,8,10] : int list
So, here is what I have so far...
fun select f l = foldl (fn (x,y) => if (f(x)) then x else 0) 0 l;
This obviously doesn't work correctly. It simply returns 10. I'm sure I need to use op:: somehow to get this to work, but I can't figure it out. My thought is that it should look something like this...
fun select f l = foldl (fn (x,y) => if (f(x)) then op:: else []) [] l;
But this does not work. Any help would be appreciated. Thanks!
You're close. The only problems are the if/else cases in the function you're passing to fold.
Remember, in your fn (x,y), x is the list element you're considering, and y is the result of folding the rest of the list. If f(x) fails, then you want to exclude x from the result, so you just pass y along. If f(x) succeeds, you want to include x in your result, so you return y#[x].
Note that it's best to avoid using the append operator (y#[x]) where you can, as it's a linear-time operation, while prepending (x::y) is constant. Of course, substituting one for the other in this case will construct your list backwards. You can get around this by folding backwards as well, i.e. using foldr instead of foldl.
What you're implementing already exists. It's called filter.
- List.filter (fn x => x mod 2 = 0) [1,2,3,4,5,6,7,8,9,10];
val it = [2,4,6,8,10] : int list
Your attempt in your second code sample is pretty close. There are several issues I might point out:
op:: is an operator, which is a function. You probably don't want to return a function. Instead, you probably want to use the operator to create a list from a head element and the rest of the list, like this: x :: y
In the else case, you are currently returning an empty list, and throwing away whatever was accumulated in y. You probably don't want to do that.
Think about whether left-fold or right-fold would be most suitable for your output