Less than function in SML - sml

I've come across 2 confusing problems in SML and was hoping someone could help me out:
The first is a function which takes an element and a list and decides whether that element exists in the list or not, here is the code I've attempted to write:
fun member (e,L) = foldl (fn(a,b) => if (e = b) then true else false) false L;
But I get bool * 'a list --> bool but what I need is ''a * ''a list --> bool
As for the second, it also requires an element and a list but returns a list of elements less than the passed one. I'm not sure whether this should be done via map or foldr/foldl.
Any suggestions?
Thanks in advance :)

Regarding the first question, in fn (a, b) => ... a is the next element and b is the accumulator. Since you compare e with b, e is infered to have type bool. You should compare e with a, and never override b when it becomes true:
fun exists (e, L) =
foldl (fn (a, b) => e = a orelse b) false L
For the second question, you can use foldr/foldl to do so. It's similar to the first example; you start with empty list as the accumulator and prepend an element to it whenever that element is smaller than a threshold.
As a tradeoff, foldr gives you the right order but it isn't tail-recursive. On the other hand, foldl is tail-recursive but gives resulting lists in a reverse order.

to see if an element is in list or not try this:
fun elementExist(e, nil) = false
| elementExist(e, x::xs) = if e = x orelse elementExist(e, xs) then true else false;
for the second one to remove the existing element from the list:
fun elFromList(e, nil) = []
| elFromList(e, x::xs) = if e = x then elFromList(e, xs) else x::elFromList(e, xs);
Good Luck!!

Related

Return elements common in both lists in Ocaml

I need to implement a method to return common elements in two lists as part of an assignment problem:
My idea was to remove duplicates in both lists, concatenate them and return elements that are repeated in the resulting list. I want to define a Boolean function that check for each elements in the list if they appear more than once. My idea was to use List.fold_left with a specific element b in the list and use acc to keep track of the number of times it appears in the list. However, I have an error here:
I have another idea that involves sorting the lists first, But the list could be of any type, hence comparison has to be implemented for new types as well. Or can I just use < to compare any type of values?
Here are the codes that I have so far.
let rec remove (b : 'a) (l : 'a list)=
match l with
| [] -> []
| w::e -> if w=b then remove b e
else w::(remove b e)
let rec removeduplicates (l:'a list)=
match l with
| [] -> []
| w::e -> w::(removeduplicates(remove w e))
let removeduppair (l : 'a list * 'a list)=
let (l1,l2) = l in
(removeduplicates l1, removeduplicates l2)
This expression has a type error:
if x = b then acc + 1
The problem is that doesn't have an else part. In other words, it doesn't say what you want the value to be when x is not equal to b.
You can fix this just by adding an else part.
A little more detail: OCaml allows you to leave off the else part, but only if the then part has unit type. In such a case, the value when the test is false will be the same as when it is true, namely () (the only value of unit type).

Updating a list of 2-tuples in SML

I'm trying to update a running list of 2-tuples in SML. This is the same problem as: How can I update lists in SML using functions?
Unfortunately, the answer doesn't help. First, here is my code:
fun member(a, []) = false
| member((a, b), (c, d)::cds) = a = c orelse member((a, b), cds);
fun update([], (loc, v)) = [(loc, v)]
| update((y, z)::yzs, (loc, v)) =
if member((loc, v), (y, z)::yzs) then
if loc = y then (loc, v)::yzs
else (y, z)::update(yzs, (loc, v))
else (y, z)::yzs#[(loc, v)];
I am able to call the update function on FLR to create new values, but can only update the last value. In addition, when the last value is added and I call the update function again, it has not appended to FLR. Here's my example:
- val FLR = [(1,1),(2,4),(3,9),(4,16),(5,25)];
val FLR = [(1,1),(2,4),(3,9),(4,16),(5,25)] : (int * int) list
- update(FLR, (6,36));
val it = [(1,1),(2,4),(3,9),(4,16),(5,25),(6,36)] : (int * int) list
- update(FLR, (7,42));
val it = [(1,1),(2,4),(3,9),(4,16),(5,25),(7,42)] : (int * int) list
Instead of assigning the value to "it," is there a way for me to assign the value of the new list to FLR? In addition, I'm not able to add new values to an empty list? Any suggestions on that?
As Yawar pointed out, your code seems to work, but the idea of mutating variables to see updates must be replaced with shadowing bindings with newly created values that slightly different.
Your code can be simplified:
fun member ((x,_), xs) = List.exists (fn (y,_) => x = y) xs
fun update ([], (x,v)) = [(x,v)]
| update ((y,w)::pairs, (x,v)) =
if x = y
then (x,v) :: pairs (* replace (y,w) with (x,v), stop *)
else (y,w) :: update (pairs, (x,v)) (* keep (y,w), continue *)
That is, you don't need memberinside update to tell you whether the list needs updating or not, since that will require member to recurse through the list and return true or false with not much else to show for where the insert/replace should occur.
It seems a little asymmetric that member takes the pair first and the list second, while update takes the list first and the pair second. When designing APIs, try and make things consistent.
Doing yzs#[(loc, v)] is bad and probably, in your case, unnecessary. This insertion of a single element will loop through the entire list with the effect of the new pair ending at the end of the list. Instead of (y, z)::yzs#[(loc, v)] you could do (loc, v)::(y, z)::yzs to reduce this to a constant-time operation.

How does one signify an infinite list to be ascending for elem checks?

I have an infinite list of primes initialized by the following list comprehension:
primes = [x | x <- [2..], 0 `notElem` map (x `mod`) [2..(x `quot` 2)]]
This allows me to make checks like 17 `elem` primes to confirm that 17 is a prime. However, when I check whether a non-prime is in the list, the program does not stop computing. I assume that this is because it does not realize that if the number cannot be found in the list before a prime that is greater than the number, it cannot be found anywhere in the list. Therefore, is there anyway in Haskell to signify to the compiler that a list contains only ascending numbers, so that an elem check will know to stop and return false if it reaches a number in the list greater than its first argument?
One possibility would be to use dropWhile:
isPrime n = (head $ dropWhile (< n) primes) == n
Sure. You can define your own OrderedList newtype, wrap the infinite list, define more efficient searching function that takes OrderedList as its argument.
newtype OrderedList a = OL [a]
member a (OL as) = case dropWhile (<a) as of
[] -> False
(x:_) -> a == x
You cannot override the behavior of elem eventhough it's a class method of Foldable, since the definition of elem only requires the underlying element type to be Eqable, namely:
member :: (Ord a, Eq a) => a -> OrderedList a -> Bool
elem :: (Eq a, Foldable t) => a -> t a -> Bool
You can verify that by the following code:
instance Foldable OrderedList where
foldMap f (OL as) = foldMap f as
elem = member -- error: Could not deduce `Ord a` arising from a use of `member`
Just a note: when your list is not infinite, you'd better consider make use of the tree-like structures (e.g. IntSet), they optimize the complexity of search operaton from O(n) to O(log(n)).
One can code it as a fold:
memberOrd :: (Eq a, Ord a) => a -> [a] -> Bool
memberOrd x = foldr (\y b -> y==x || y<x && b) False
The laziness of || makes it work on infinite lists as well.
(Clearly, we must assume that the list does not contain infinitely many elements < x. We are not suddenly able to solve undecidable problems... ;-) )
Will Ness below suggests the following variant, which performs fewer comparisons:
memberOrd x = foldr (\y b -> y<x && b || y==x) False

filtering values into two lists

So i'm new to sml and am trying to understand the ins/out out of it. Recently i tried creating a filter which takes two parameters: a function (that returns a boolean), and a list of values to run against the function. What the filter does is it returns the list of values which return true against the function.
Code:
fun filter f [] = [] |
filter f (x::xs) =
if (f x)
then x::(filter f xs)
else (filter f xs);
So that works. But what i'm trying to do now is just a return a tuple that contains the list of true values, and false. I'm stuck on my conditional and I can't really see another way. Any thoughts on how to solve this?
Code:
fun filter2 f [] = ([],[]) |
filter2 f (x::xs) =
if (f x)
then (x::(filter2 f xs), []) (* error *)
else ([], x::(filter2 f xs)); (* error *)
I think there are several ways to do this.
Reusing Filter
For instance, we could use a inductive approach based on the fact that your tuple would be formed by two elements, the first is the list of elements that satisfy the predicate and the second the list of elements that don't. So, you could reuse your filter function as:
fun partition f xs = (filter f xs, filter (not o f) xs)
This is not the best approach, though, because it evaluates the lists twice, but if the lists are small, this is quite evident and very readable.
Folding
Another way to think about this is in terms of fold. You could think that you are reducing your list to a tuple list, and as you go, you split your items depending on a predicate. Somwewhat like this:
fun parition f xs =
let
fun split x (xs,ys) =
if f x
then (x::xs,ys)
else (xs, x::ys)
val (trueList, falseList) = List.foldl (fn (x,y) => split x y)
([],[]) xs
in
(List.rev trueList, List.rev falseList)
end
Parition
You could also implement your own folding algorithm in the same way as the List.parition method of SML does:
fun partition f xs =
let
fun iter(xs, (trueList,falseList)) =
case xs of
[] => (List.rev trueList, List.rev falseList)
| (x::xs') => if f x
then iter(xs', (x::trueList,falseList))
else iter(xs', (trueList,x::falseList))
in
iter(xs,([],[]))
end
Use SML Basis Method
And ultimately, you can avoid all this and use SML method List.partition whose documentation says:
partition f l
applies f to each element x of l, from left to right, and returns a
pair (pos, neg) where pos is the list of those x for which f x
evaluated to true, and neg is the list of those for which f x
evaluated to false. The elements of pos and neg retain the same
relative order they possessed in l.
This method is implemented as the previous example.
So I will show a good way to do it, and a better way to do it (IMO). But the 'better way' is just for future reference when you learn:
fun filter2 f [] = ([], [])
| filter2 f (x::xs) = let
fun ftuple f (x::xs) trueList falseList =
if (f x)
then ftuple f xs (x::trueList) falseList
else ftuple f xs trueList (x::falseList)
| ftuple _ [] trueList falseList = (trueList, falseList)
in
ftuple f (x::xs) [] []
end;
The reason why yours does not work is because when you call x::(filter2 f xs), the compiler is naively assuming that you are building a single list, it doesn't assume that it is a tuple, it is stepping into the scope of your function call. So while you think to yourself result type is tuple of lists, the compiler gets tunnel vision and thinks result type is list. Here is the better version in my opinion, you should look up the function foldr if you are curious, it is much better to employ this technique since it is more readable, less verbose, and much more importantly ... more predictable and robust:
fun filter2 f l = foldr (fn(x,xs) => if (f x) then (x::(#1(xs)), #2(xs)) else (#1(xs), x::(#2(xs)))) ([],[]) l;
The reason why the first example works is because you are storing default empty lists that accumulate copies of the variables that either fit the condition, or do not fit the condition. However, you have to explicitly tell SML compiler to make sure that the type rules agree. You have to make absolutely sure that SML knows that your return type is a tuple of lists. Any mistake in this chain of command, and this will result in failure to execute. Hence, when working with SML, always study your type inferences. As for the second one, you can see that it is a one-liner, but I will leave you to research that one on your own, just google foldr and foldl.

Using fold_left to search for an element in OCaml

I'm wondering how can I build a function in Ocaml that uses List.fold_left to find out if an element exists in a list.
Example:
exists 3 [1;2;3;4;5]
=> true
The type of this function is: a -> bool -> 'a list -> bool
My idea how to do it is as follows:
let exists k l = List.fold_left( fun a x-> a=x) k l
but obviously is wrong. Any suggestion how to do it?
let exists k l =
List.fold_left (fun b x -> b || x = k) false l
Two comments on #tonio's answer:
Use || instead of superfluous if ... then true else ....
Use structural equality (=) instead of reference equality (==) for comparing values.
Moreover, exists is available in List module. The built-in function is more efficient since it doesn't have to go through the whole list every time.
You should use something like
let exists k l =
List.fold_left(
fun a x -> if x == k then true else a)
false l
;;
You have an initial value of false, and pass it while iterating over the list. Once the searched element is found, set the value to true, and pass it along. If the element in the list is not what you search, pass the value you had as input: it is either the initial false, or true if the element you search for has already been found.
after the hints taken by the answers i could be able to improve it more.
Here is my solution
let exists' f l =List.fold_left(fun a b-> f b || a ) false l;;
Like this, this function is more abstract and can be used for any predicate f.