SML - Multiplying Coefficients of Polynomials - list

I have two lists that contain coefficients for two different polynomials, and I'm looking to write a function that can multiply them together (i.e F-O-I-L).
The function I wrote is not complete, however I was just using it to test my understanding of how it should work.
fun polyMult(nil, nil) = nil
| polyMult(M as x::xs, N as y::ys) =
(x * y)::polyMult(xs, ys);
Am I on the right track?
Also, I have an error message stating uncaught exception Match [nonexhaustive match failure]
What does that mean?

Unfortunately, you are not on the right track. Your function just zips the two lists with multiplication, which is not how F-O-I-L works. By definition of polynomial multiplication, your function should return a polynomial of a higher degree. This should be helpful for you to understand F-O-I-L.
The nonexhaustive match error means that you are not covering all the possible cases for the two lists in your pattern matching. In fact, you are missing the two cases where one of the lists is nil and the other one is not. In terms of your function this would mean the cases where the function has the lists of coefficients from polynomials of different degrees.
If you want to separately handle those two cases you are currently missing, you can go like this:
fun polyMult(M, N) = case (M,N) of
([], []) => []
| ([], y::ys) => ...
| (x::xs, []) => ...
| (x::xs, y::ys) => ...
Of course, replace the dots with your implementation. I hope this helps, good luck.

You need to do this
fun foldL F y nil = y
| foldL F y (x::xr) = foldL F (F(x,y)) xr;
fun polymult(M:real list, nil) = nil
| polymult(nil, N) = nil
| polymult(m::mr, N) = foldL(fn(x,a) => x * a) m N::polymult(mr,N);
thatll do what you want it to.

Related

SML Multiple Set Intersection Function

I need to write a function in SML that takes an arbitrary number of lists as input and returns the intersection of all the sets given. For example, the function needs to have the following form:
multiSetIntersection([s1,s2,s3,s4]) = (Intersection of s1,s2,s3,s4)
I have been able to write the intersection function that takes in two lists as follows:
fun intersec([], y) = []
| intersec(x::xs, y) =
if memberOf(x,y) then x::intersec(xs,y)
else intersec(xs,y)
But I am unable to "generalize" this function to take in an arbitrary number of lists as input. I have tried the following:
fun multiSetIntersection([]) = []
| multiSetIntersection((x::xs)::y) =
if memberOf(x,y) then x::multiSetIntersection([xs,y])
else multiSetIntersection([xs,y])
But this is giving me some type mismatch errors and will not work properly. Can anybody help me or give me some tips in order to write this function?
Thank you!
Using this intersection function
fun intersect ([], _) = []
| intersect (x::xs, ys) =
if List.exists (fn y => x = y) ys
then x :: intersect (xs, ys)
else intersect (xs, ys)
To do a multiple set intersection, there are 3 cases.
If there are no sets, the intersection is [].
If there is one set xs, the intersection is that set.
If there are more than two sets, the intersection is the intersect of the first set and the intersection of all the remaining sets.
Putting these four cases together we get:
fun intersects [] = []
| intersects [xs] = xs
| intersects (xs::xss) = intersect (xs, intersects xss);;

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.

SML function to with 2 lists that returns the XOR---fixed

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.

Using Haskell's map function to calculate the sum of a list

Haskell
addm::[Int]->Int
addm (x:xs) = sum(x:xs)
I was able to achieve to get a sum of a list using sum function but is it possible to get the sum of a list using map function? Also what the use of map function?
You can't really use map to sum up a list, because map treats each list element independently from the others. You can use map for example to increment each value in a list like in
map (+1) [1,2,3,4] -- gives [2,3,4,5]
Another way to implement your addm would be to use foldl:
addm' = foldl (+) 0
Here it is, the supposedly impossible definition of sum in terms of map:
sum' xs = let { ys = 0 : map (\(a,b) -> a + b) (zip xs ys) } in last ys
this actually shows how scanl can be implemented in terms of map (and zip and last), the above being equivalent to foldl (+) 0 xs === last $ scanl (+) 0 xs:
scanl' f z xs = let { ys = z : map (uncurry f) (zip ys xs) } in ys
I expect one can calculate many things with map, arranging for all kinds of information flow through zip.
edit: the above is just a zipWith in disguise of course (and zipWith is kind of a map2):
sum' xs = let { ys = 0 : zipWith (+) ys xs } in last ys
This seems to suggest that scanl is more versatile than foldl.
It is not possible to use map to reduce a list to its sum. That recursive pattern is a fold.
sum :: [Int] -> Int
sum = foldr (+) 0
As an aside, note that you can define map as a fold as well:
map :: (a -> b) -> ([a] -> [b])
map f = fold (\x xs -> f x : xs) []
This is because foldr is the canonical recursive function on lists.
References: A tutorial on the universality and expressiveness of fold, Graham Hutton, J. Functional Programming 9 (4): 355–372, July 1999.
After some insights I have to add another answer: You can't get the sum of a list with map, but you can get the sum with its monadic version mapM. All you need to do is to use a Writer monad (see LYAHFGG) over the Sum monoid (see LYAHFGG).
I wrote a specialized version, which is probably easier to understand:
data Adder a = Adder a Int
instance Monad Adder where
return x = Adder x 0
(Adder x s) >>= f = let Adder x' s' = f x
in Adder x' (s + s')
toAdder x = Adder x x
sum' xs = let Adder _ s = mapM toAdder xs in s
main = print $ sum' [1..100]
--5050
Adder is just a wrapper around some type which also keeps a "running sum." We can make Adder a monad, and here it does some work: When the operation >>= (a.k.a. "bind") is executed, it returns the new result and the value of the running sum of that result plus the original running sum. The toAdder function takes an Int and creates an Adder that holds that argument both as wrapped value and as running sum (actually we're not interested in the value, but only in the sum part). Then in sum' mapM can do its magic: While it works similar to map for the values embedded in the monad, it executes "monadic" functions like toAdder, and chains these calls (it uses sequence to do this). At this point, we get through the "backdoor" of our monad the interaction between list elements that the standard map is missing.
Map "maps" each element of your list to an element in your output:
let f(x) = x*x
map f [1,2,3]
This will return a list of the squares.
To sum all elements in a list, use fold:
foldl (+) 0 [1,2,3]
+ is the function you want to apply, and 0 is the initial value (0 for sum, 1 for product etc)
As the other answers point out, the "normal" way is to use one of the fold functions. However it is possible to write something pretty similar to a while loop in imperative languages:
sum' [] = 0
sum' xs = head $ until single loop xs where
single [_] = True
single _ = False
loop (x1 : x2 : xs) = (x1 + x2) : xs
It adds the first two elements of the list together until it ends up with a one-element list, and returns that value (using head).
I realize this question has been answered, but I wanted to add this thought...
listLen2 :: [a] -> Int
listLen2 = sum . map (const 1)
I believe it returns the constant 1 for each item in the list, and returns the sum!
Might not be the best coding practice, but it was an example my professor gave to us students that seems to relate to this question well.
map can never be the primary tool for summing the elements of a container, in much the same way that a screwdriver can never be the primary tool for watching a movie. But you can use a screwdriver to fix a movie projector. If you really want, you can write
import Data.Monoid
import Data.Foldable
mySum :: (Foldable f, Functor f, Num a)
=> f a -> a
mySum = getSum . fold . fmap Sum
Of course, this is silly. You can get a more general, and possibly more efficient, version:
mySum' :: (Foldable f, Num a) => f a -> a
mySum' = getSum . foldMap Sum
Or better, just use sum, because its actually made for the job.

How to takeWhile elements in a list wrapped in a monad

Got a little puzzle I was wondering if you could help me clarify.
Let's define a function that returns a list:
let f = replicate 3
What we want to do is map this function to an infinite list, concatenate the results, and then take only things that match a predicate.
takeWhile (< 3) $ concatMap f [1..]
Great! That returns [1,1,1,2,2,2], which is what I want.
Now, I want to do something similar, but the function f now wraps its results in a Monad. In my usecase, this is the IO monad, but this works for discussing my problem:
let f' x = Just $ replicate 3 x
To map and concat, I can use:
fmap concat $ mapM f' [1..5]
That returns: Just [1,1,1,2,2,2,3,3,3,4,4,4,5,5,5]
If I want to use takeWhile, this still works:
fmap (takeWhile (< 3) . concat) $ mapM f' [1..5]
Which returns: Just [1,1,1,2,2,2]. Great!
But, if I make the list over which I map an infinite list this does not do what I expected:
fmap (takeWhile (< 3) . concat) $ mapM f' [1..]
Seems like the takeWhile is never happening. Somehow, I'm not getting the lazy computation I was expecting. I’m a bit lost.
The problem isn't that fmap + takeWhile doesn't work with infinite lists wrapped in a monad. The problem is that mapM can't produce an infinite list (at least not in the Maybe monad).
Think about it: If f' returns Nothing for any item in the list, mapM has to return Nothing. However mapM can't know whether that will happen until it has called f' on all items in the list. So it needs to iterate through the whole list before it knows whether the result is Nothing or Just. Obviously that's a problem with infinite lists.
This should do the trick:
takeWhileM :: (Monad m) => (a -> Bool) -> [m a] -> m [a]
takeWhileM p [] = return []
takeWhileM p (m:ms) = do
x <- m
if p x
then liftM (x:) (takeWhileM p ms)
else return []
See sepp2k's answer for an explanation of why you are losing laziness. The Identity monad or the nonempty list monad, for example, wouldn't have this problem.
You can't mapM an infinite list of Maybes. mapM is map followed by sequence. Here is the definition of sequence:
sequence ms = foldr k (return []) ms
where
k m m' = do { x <- m; xs <- m'; return (x:xs) }
From this we see that sequence evaluates every monadic value in the list. Since it's an infinite list, this operation will not terminate.
EDIT:
luqui and Carl make a good point that this doesn't generalize to any monad. To see why it doesn't work for Maybe we need to look at the implementation of (>>=):
(>>=) m k = case m of
Just x -> k x
Nothing -> Nothing
The important point here is that we do a case on m. This makes the m strict because we have to evaluate it to figure out how to continue execution. Note that we're not casing on x here, so it remains lazy.