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
Related
I need to implement a powerset function in ML that takes a list of ints with the following contraints:
1) Never call built in library functions except map, foldr, and foldl.
2) Never be recursive. All recursion occur within map and fold
3) Never contain let or local expressions
I've already implemented the function without these constraints using normal recursion of the form:
Powerset(x::xs) = powerset(xs) # x.powerset(xs)
I'm having trouble thinking of a way to translate this type of implementation into one that uses only maps and folds.
I'm not necessarily asking for someone to implement it for me, but I would appreciate a nudge in the right direction or any help for that matter.
Thakns
Here's how I go about solving problems with folds.
Think about the final value you want to obtain. In your case, this would be the powerset of the input list. The crucial question is now this: can the powerset of a list be recomputed after inserting a new element? That is, given P(S), the powerset of some set of items S, it is possible to compute P(S ∪ {x}) in terms of only P(S) and x?
I believe you've already answered this question definitively above. Not explicitly, perhaps, but if you rework your Powerset function, you'll find that the right idea is hidden in it. You'll want to package up this code into a little helper function:
fun extendPowerset (PS : 'a list list, x : 'a) : 'a list list =
(* PS is the powerset of some set S. This function
* should return the powerset of S ∪ {x}. *)
...
Great, now how do you plug that into a fold? Well, at each step of the fold, you are given two things:
the next element of the list, and
some value computed from all previous elements (think of this as a "summary" of the previous elements)
In return, you must compute a slightly larger summary: it should summarize the next element in addition to all previous. Doesn't this feel vaguely similar? The extendPowerset function is basically doing exactly what you need, where the "summary" of the previous elements is the powerset of those elements. I'll leave the rest to you.
Aside: note that you can also append two lists with a fold. As a hint, try working out what value is computed by foldl op:: [1,2] [3,4]. It's not quite like appending [1,2] and [3,4], but it's close...
Like you have already done, I would also first write a powerset function using explicit recursion. I would then try and discover the higher-order functional patterns and substitute those afterwards, one pattern at a time.
You might for example turn a helper function
fun consMany (x, []) = []
| consMany (x, L::Ls) = (x::L) :: consMany (x, Ls)
into the expression
map (fn L => x::L) Ls
You might eliminate a let-expression (useful for re-using a once-computed value twice)
fun foo (x::xs) =
let val rest = foo xs
in ... x ... rest ... rest ...
end
using a function:
fun foo (x::xs) =
bar (x, foo xs)
and bar (x, rest) = ... x ... rest ... rest ...
although, this might as well be an anonymous function:
fun foo (x::xs) =
(fn rest => ... x ... rest ... rest ...) (foo xs)
And you might turn a list-recursive function
fun derp [] = ...
| derp (x::xs) = g (x, derp xs)
into the fold:
fun derp xs = foldr g (...) xs
but if the order of your results don't matter, foldl is tail-recursive.
How would I go about counting the occurrence of a particular element in a list in Ocaml?
count 2 [1;2;2;2;2;3;4;5] # should return 4
I am having trouble figuring out how fold works and how I would apply it here. I tried doing:
count element list = fold (fun f ele head -> if ele = head then 1 else 0) 0 list
But this keeps returning 0 for my tests?
Your code is quite close. Forgive me, but I'll assume you're something of a beginner in OCaml.
In the expression fun f ele head -> ..., you're defining a function with three parameters named f, ele, and head. I suspect that you intended the f as a name for the function. But lambdas (function expressions) in OCaml don't have names (as they do in, say, JavaScript).
There is no standard function fold in OCaml. Let's assume you're working with a left fold, List.fold_left. The function to be folded takes two parameters: the first is the accumulated result from previous calls of the function, and the second is the new element from the list.
So your internal function should look more like this:
fun accum ele -> ....
The folded function returns the new accumulated result. So obviously you don't want to return just 0 or 1. You want to return the new count.
I don't want to say more, as I suspect this is part of a school assignment. I hope this helps.
(As a side comment, this question isn't about recursion. The recursion is handled for you by List.fold_left, you just need to fill in the function and initial value.)
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 building some equations in F#, and when working on my polynomial class I found some odd behavior using List.mapi
Basically, each polynomial has an array, so 3*x^2 + 5*x + 6 would be [|6, 5, 3|] in the array, so, when adding polynomials, if one array is longer than the other, then I just need to append the extra elements to the result, and that is where I ran into a problem.
Later I want to generalize it to not always use a float, but that will be after I get more working.
So, the problem is that I expected List.mapi to return a List not individual elements, but, in order to put the lists together I had to put [] around my use of mapi, and I am curious why that is the case.
This is more complicated than I expected, I thought I should be able to just tell it to make a new List starting at a certain index, but I can't find any function for that.
type Polynomial() =
let mutable coefficients:float [] = Array.empty
member self.Coefficients with get() = coefficients
static member (+) (v1:Polynomial, v2:Polynomial) =
let ret = List.map2(fun c p -> c + p) (List.ofArray v1.Coefficients) (List.ofArray v2.Coefficients)
let a = List.mapi(fun i x -> x)
match v1.Coefficients.Length - v2.Coefficients.Length with
| x when x < 0 ->
ret :: [((List.ofArray v1.Coefficients) |> a)]
| x when x > 0 ->
ret :: [((List.ofArray v2.Coefficients) |> a)]
| _ -> [ret]
I think that a straightforward implementation using lists and recursion would be simpler in this case. An alternative implementation of the Polynomial class might look roughly like this:
// The type is immutable and takes initial list as constructor argument
type Polynomial(coeffs:float list) =
// Local recursive function implementing the addition using lists
let rec add l1 l2 =
match l1, l2 with
| x::xs, y::ys -> (x+y) :: (add xs ys)
| rest, [] | [], rest -> rest
member self.Coefficients = coeffs
static member (+) (v1:Polynomial, v2:Polynomial) =
// Add lists using local function
let newList = add v1.Coefficients v2.Coefficients
// Wrap result into new polynomial
Polynomial(newList)
It is worth noting that you don't really need mutable field in the class, since the + operator creates and returns a new instance of the type, so the type is fully immutable (as you'd usually want in F#).
The nice thing in the add function is that after processing all elements that are available in both lists, you can simply return the tail of the non-empty list as the rest.
If you wanted to implement the same functionality using arrays, then it may be better to use a simple for loop (since arrays are, in principle, imperative, the usual imperative patterns are usually the best option for dealing with them). However, I don't think there is any particular reason for preferring arrays (maybe performance, but that would have to be evaluated later during the development).
As Pavel points out, :: operator appends a single element to the front of a list (see the add function above, which demonstrates that). You could write what you wanted using # which concatenates lists, or using Array.concat (which concatenates a sequence of arrays).
An implementation using higher-order functions and arrays is also possible - the best version I can come up with would look like this:
let add (a1:_[]) (a2:_[]) =
// Add parts where both arrays have elements
let l = min a1.Length a2.Length
let both = Array.map2 (+) a1.[0 .. l-1] a2.[0 .. l-1]
// Take the rest of the longer array
let rest =
if a1.Length > a2.Length
then a1.[l .. a1.Length - 1]
else a2.[l .. a2.Length - 1]
// Concatenate them
Array.concat [ both; rest ]
add [| 6; 5; 3 |] [| 7 |]
This uses slices (e.g. a.[0 .. l]) which give you a part of an array - you can use these to take the parts where both arrays have elements and the remaining part of the longer array.
I think you're misunderstanding what operator :: does. It's not used to concatenate two lists. It's used to prepend a single element to the list. Consequently, it's type is:
'a -> 'a list -> 'a list
In your case, you're giving ret as a first argument, and ret is itself a float list. Consequently, it expects the second argument to be of type float list list - hence why you need to add an extra [] to the second argument to make it to compile - and that will also be the result type of your operator +, which is probably not what you want.
You can use List.concat to concatenate two (or more) lists, but that is inefficient. In your example, I don't see the point of using lists at all - all this converting back & forth is going to be costly. For arrays, you can use Array.append, which is better.
By the way, it's not clear what is the purpose of mapi in your code at all. It's exactly the same as map, except for the index argument, but you're not using it, and your mapping is the identity function, so it's effectively a no-op. What's it about?
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.