I am trying to retrieve the last element of a list using foldl in SML, and not getting a lot of correct answers from what i have done already, the following is one of my bad tries, any help!
fun last p = foldr ( fn (x, y) => if ( p y ) then x else y ) [];
You could use List.last even though you should be careful, as it will raise an exception if you use it on an empty list.
For the MosML implementation, you can find the documentation at http://mosml.org/mosmllib/List.html#last-val
As RasmusWL mentioned, List.last is the appropriate tool for general use.
It can be recreated using foldl:
fun last(alist, init) = List.foldl (fn(x,y) => x) init alist
This produces a signature: fn : 'a list * 'a -> 'a
To write it with foldr use:
fun last(alist, init) = List.foldr (fn(x,y) => x) init (List.rev alist)
An advantage of using foldl is that it does not require a check for an empty list:
List.foldl (fn(x,y) => x) 0 [];
(* val it = 0 : int *)
Related
I need to write a function that takes a list of strings and finds the largest string in the list. In case of tie, it should return string closest to the end of the list. The catch is it needs to iterate through the list using List.foldl and cannot use recursive calls except for those in the library function of List,foldl.
The following code works fine.
fun longest_string2 str_list =
List.foldl(fn (x, acc) => if String.size x >= String.size acc then x else acc) "” str_list
If I run longest_string2 ["Apple", "ball", "Bpple”]; in REPL, I get val it = "Bpple" : string
However, if I reverse the arguments of anonymous function as below I get val it = "Apple" : string.
Since the anonymous function is accessing the elements by name and not position, why does this makes difference?
The definition of List.foldl is
fun foldl (f: 'a*'b->'b) (acc: 'b) (l: 'a list): 'b =
case l of
[] => acc
| x::xs => foldl f (f(x,acc)) xs
If you reverse arguments of the anonymous function, your function becomes the following: (correct me if I misinterpreted your question)
fun longest_string2 str_list =
List.foldl(fn (acc, x) => if String.size x >= String.size acc then x else acc) "” str_list
If your pass ["Apple", "ball", "Bpple”] as argument to longest_string2 now, the foldl function will pattern match your list with x::xs, where x is “Apple” and xs is ["ball", "Bpple”]. When you compute the updated accumulator using f(x, acc), x and acc gets swapped. In other words, in your anonymous function (with reversed arguments), you would be assuming that the first argument would be ”” and the second argument would be Apple but the implementation of List.foldl will pass f(“Apple”, “”). In this case, your anonymous function will label “Apple” as “acc” and “” as “x”.
#3123 has most answered the question, but has not directly addressed this statement in the question.
Since the anonymous function is accessing the elements by name and not
position, why does this makes difference?
foldl takes a function which takes a tuple as its argument, which is positional.
We could define a fold function which takes a record as its argument instead if we really wanted to achieve this:
fun namedFold _ acc [] = acc
| namedFold f acc (x::xs) =
namedFold f (f {acc=acc, x=x}) xs;
And then call it as:
namedFold (fn { acc, x } => acc + x) 0 [1,2,3,4]
Or as:
namedFold (fn { x, acc } => acc + x) 0 [1,2,3,4]
And get the same result.
But then the type of namedFold is fn :({acc: 'a, x: 'b} -> 'a) -> 'a -> 'b list -> 'a and it becomes essentially impossible to easily pass existing functions to it. With foldl defined the way it is, we can easily rewrite that previous called to namedFold as:
foldl op+ 0 [1,2,3,4]
Because op+ has the same signature as the first argument to foldl.
I'm trying to make a function which can return the specific nth element of lazylist.
Here is what I made:
datatype 'a lazyList = nullList
| cons of 'a * (unit -> 'a lazyList)
fun Nth(lazyListVal, n) = (* lazyList * int -> 'a option *)
let fun iterator (laztListVal, cur, target) =
case lazyListVal of
nullList => NONE
| cons(value, tail) => if cur = target
then SOME value
else iterator (tail(), cur+1, target)
in
iterator(lazyListVal,1,n)
end
I expected the result that as recusing proceeds, eventually the variable cur gets same as the variable target, and then the function iterator returns SOME value so it will return the final nth element.
But when I compile it and run, it only returns the very first element however I test with the lazylist objects.
Please figure what is the problem. I have no idea...
cf) I made another function which is relevant to this problem, the function that transforms lazylist into SML original list containing the first N values. Codes above:
fun firstN (lazyListVal, n) = (* lazyList * int -> 'a list *)
let fun iterator (lazyListVal, cur, last) =
case lazyListVal of
nullList => []
| cons(value, tail) => if cur = last
then []
else value::iterator(tail(),cur+1,last)
in
iterator(lazyListVal,0,n)
end
The strange thing is the function firstN is properly working.
The problem is that your iterator function does case lazyListVal of ..., but the recursive tail is called laztListVal, so for every iteration, it keeps looking at the first list. Use better variable names to avoid this kind of "invisible" bug.
For a simpler definition of nth:
datatype 'a lazyList = NullList | Cons of 'a * (unit -> 'a lazyList)
fun nth (NullList, _) = NONE
| nth (Cons (x, xs), 0) = SOME x
| nth (Cons (_, xs), n) = nth (xs (), n-1)
val nats = let fun nat n = Cons (n, fn () => nat (n+1)) in nat 0 end
val ten = nth (nats, 10)
Edit: While function pattern matching is ideal here, you could also have used a case ... of ... here. A helper function seems unnecessary, though, since you can simply use the input argument n as the iterator:
fun nth (L, n) =
case (L, n) of
(NullList, _) => NONE
| (Cons (x, xs), 0) => SOME x
| (Cons (_, xs), n) => nth (xs (), n-1)
You may however want to make the function more robust:
fun nth (L, n) =
let fun nth' (NullList, _) = NONE
| nth' (Cons (x, xs), 0) = SOME x
| nth' (Cons (_, xs), n) = nth' (xs (), n-1)
in if n < 0 then NONE else nth' (L, n) end
Here having a helper function ensures that n < 0 is only checked once.
(You could also raise Domain, since negative indices are not well-defined.)
I'm trying to "double" filter through two lists depending on passing a datatype test painfully without recursion using HOPs. Below is my very-ugly attempt at a solution...
datatype 'a test = Test of ('a -> bool) * string;
fun foo xs lst =
let
fun foo_bar(x, ls) =
let
val tests = (List.filter (fn (Test(f, str)) => (f x)) ls)
in
(List.map (fn (Test(f, str)) => str) tests)
end
in
(List.map (fn x => foo_bar(x, lst)) xs)
end;
allPass: 'a list -> 'a test list -> 'a test list;
allPass [1, 2, 40, 150] [positive, even] should return the string "pos".
Currently, my function is returning a nested list: [["pos"], ["pos even"], ["pos even"], ["pos even"]]. Is there a non-recursive way to extract just "pos" from this result or am I going about solving this problem in entirely the wrong direction?
You're going in the right direction, but you're not quite there yet. Here's what I think you want.
Take a list of value and a list of Tests. Return a list of the names of the tests for which all of the values pass.
Okay, so we need to:
Filter the list of tests. The predicate for a test is that all the values must pass.
Extract the names of the tests that passed.
Okay, so how do we figure out if all the values in a list pass one test? Simple, we use List.all.
List.all : ('a -> bool) -> 'a list -> bool
We can define a function:
fun allPassesTest xs (Test(f,s)) = List.all f xs
This will return true if and only if all of the values in xs pass the test. Now we filter the list of tests, based on this function:
fun allPass xs tests = List.filter allPassesTest xs tests
However, this returns a 'a test list instead of a string list, so you'll need to extract the names.
fun name (Test(f,s)) = s
fun allPass xs tests = map name (List.filter allPassesTest xs tests)
Anyone able to offer any advice for a function in SML that will take 2 lists and return the XOR of them, so that if you have the lists [a,b,c,d], [c,d,e,f] the function returns [a,b,e,f] ?
I have tried to do it with 2 functions, but even that does not work properly.
fun del(nil,L2) = nil
|del(x::xs,L2)=
if (List.find (fn y => y = x) L2) <> (SOME x) then
del(xs, L2) # [x]
else
del(xs, L2);
fun xor(L3,L4) =
rev(del(L3,L4)) # rev(del(L4,L3));
Your attempt seems almost correct, except that fn x => x = x does not make sense, since it always returns true. I think you want fn y => y = x instead.
A couple of other remarks:
You can replace your use of List.find with List.filter which is closer to what you want.
Don't do del(xs,L) # [x] for the recursive step. Appending to the end of the list has a cost linear to the length of the first list, so if you do it in every step, your function will have quadratic runtime. Do x :: del(xs,L) instead, which also allows you to drop the list reversals in the end.
What you call "XOR" here is usually called the symmetric difference, at least for set-like structures.
The simplest way would be to filter out duplicates from each list and then concatenate the two resulting lists. Using List.filter you can remove any element that is a member (List.exists) of the other list.
However that is quite inefficient, and the below code is more an example of how not to do it in real life, though it is "functionally" nice to look at :)
fun symDiff a b =
let
fun diff xs ys =
List.filter (fn x => not (List.exists ( fn y => x = y) ys)) xs
val a' = diff a b
val b' = diff b a
in
a' # b'
end
This should be a better solution, that is still kept simple. It uses the SML/NJ specific ListMergeSort module for sorting the combined list a # b.
fun symDiff1 a b =
let
val ab' = ListMergeSort.sort op> (a # b)
(* Remove elements if they occur more than once. Flag indicates whether x
should be removed when no further matches are found *)
fun symDif' (x :: y :: xs) flag =
(case (x = y, flag) of
(* Element is not flagged for removal, so keep it *)
(false, false) => x :: symDif' (y :: xs) false
(* Reset the flag and remove x as it was marked for removal *)
| (false, true) => symDif' (y::xs) false
(* Remove y and flag x for removal if it wasn't already *)
| (true, _) => symDif' (x::xs) true)
| symDif' xs _ = xs
in
symDif' ab' false
end
However this is still kind of stupid. As the sorting function goes through all elements in the combined list, and thus it also ought to be the one that is "responsible" for removing duplicates.
I'm currently trying to extend a friend's OCaml program. It's a huge collection of functions needed for some data analysis.. Since I'm not really an OCaml crack I'm currently stuck on a (for me) strange List implementation:
type 'a cell = Nil
| Cons of ('a * 'a llist)
and 'a llist = (unit -> 'a cell);;
I've figured out that this implements some sort of "lazy" list, but I have absolutely no idea how it really works. I need to implement an Append and a Map Function based on the above type. Has anybody got an idea how to do that?
Any help would really be appreciated!
let rec append l1 l2 =
match l1 () with
Nil -> l2 |
(Cons (a, l)) -> fun () -> (Cons (a, append l l2));;
let rec map f l =
fun () ->
match l () with
Nil -> Nil |
(Cons (a, r)) -> fun () -> (Cons (f a, map f r));;
The basic idea of this implementation of lazy lists is that each computation is encapsulated in a function (the technical term is a closure) via fun () -> x.
The expression x is then only evaluated when the function is applied to () (the unit value, which contains no information).
It might help to note that function closures are essentially equivalent to lazy values:
lazy n : 'a Lazy.t <=> (fun () -> n) : unit -> 'a
force x : 'a <=> x () : 'a
So the type 'a llist is equivalent to
type 'a llist = 'a cell Lazy.t
i.e., a lazy cell value.
A map implementation might make more sense in terms of the above definition
let rec map f lst =
match force lst with
| Nil -> lazy Nil
| Cons (hd,tl) -> lazy (Cons (f hd, map f tl))
Translating that back into closures:
let rec map f lst =
match lst () with
| Nil -> (fun () -> Nil)
| Cons (hd,tl) -> (fun () -> Cons (f hd, map f tl))
Similarly with append
let rec append a b =
match force a with
| Nil -> b
| Cons (hd,tl) -> lazy (Cons (hd, append tl b))
becomes
let rec append a b =
match a () with
| Nil -> b
| Cons (hd,tl) -> (fun () -> Cons (hd, append tl b))
I generally prefer to use the lazy syntax, since it makes it more clear what's going on.
Note, also, that a lazy suspension and a closure are not exactly equivalent. For example,
let x = lazy (print_endline "foo") in
force x;
force x
prints
foo
whereas
let x = fun () -> print_endline "foo" in
x ();
x ()
prints
foo
foo
The difference is that force computes the value of the expression exactly once.
Yes, the lists can be infinite. The code given in the other answers will append to the end of an infinite list, but there's no program you can write than can observe what is appended following an infinite list.