How do I check if two Maps are equal in OCaml - ocaml

How do you check if two maps are equal in OCaml no matter the order ?
For example :
Map 1 :
var1 -> [Neg]
var2 -> [Pos; Zero; Neg]
var3 -> [Neg; Pos]
Map2 :
var1 -> [Neg]
var2 -> [Pos; Zero; Neg]
var3 -> [Pos; Neg]
What I've tried :
Map.equal (fun x y -> x = y)
This returns false, as it considers the order is important.
Should I sort the lists, or is there a more efficient functional way ?
Thanks

The document for Map.equal says:
equal cmp m1 m2 tests whether the maps m1 and m2 are equal,
that is, contain equal keys and associate them with equal data.
cmp is the equality predicate used to compare the data associated
with the keys.
You are specifically asking to use = as your equality predicate, but you're also saying that it's not what you want.
The solution is to supply the equality predicate that you do want.
If you want to know whether two lists contain the same elements regardless of order, you can sort the lists and compare the sorted values.
let equal_contents a b =
List.sort compare a = List.sort compare b
You can also keep the values in the map in a canonical order (i.e., sorted). Then the code you give above will work.

Related

Haskell: Sorting a List of Trees

I have a list of trees that have associated numerical values (we can treat it like sorting a list of Ints for this case) and I want to sort the whole list from highest to lowest and return the new sorted list. How do I do this? I have encountered the built in list sorting functions such as sortBy but I don't understand how to implement it.
I'm also new to coding in general if it wasn't obvious ;)
Basically, you can write your function
score :: Tree -> Int
providing a score for each of your trees. The score above is an Int, but any other ordered type can do as a score.
Then, you can use
sortBy (flip $ comparing score) myListOfTree
to sort according to the score. Remember to import Data.Ord for comparing.
Note that this can compute the score more than once. If your score function is expensive, you might want instead to precompute the scores as follows:
map snd . sortBy (flip $ comparing fst) . map (\t -> (score t, t)) $ myListOfTree
Another option is to define your own comparison function directly
compareTree :: Tree -> Tree -> Ordering
compareTree t1 t2 | someCondition = LT -- t1 < t2
| someOtherCondiction = EQ -- t1 == t2
| otherwise = GT -- t1 > t2
where in the conditions you can use your score function, if you want.
Then use sortBy compareTree to do sort in ascending order, or sortBy (flip compareTree) for the descending sort.
If this ordering it the only "natural" ordering for your Tree type, you can even declare it such:
instance Ord Tree where
compare = compareTree
(Note however that this approach will call compareTree many times, one for every comparison, possibly computing the score over and over. Hence, the map solution shown above might still be preferred.)

How to use if-then-else in a recursive function

I am writing a function that will take a list of list and merge it into sorted pairs of list. For example [[1],[9],[8],[7],[4],[5],[6]] would return [[1,9],[7,8],[4,5],[6]]. This is my first attempt at SML. I keep getting this error: operator and operand don't agree [overload conflict].
fun mergePass[] = []
| mergePass(x::[]) = x::[]
| mergePass(x::y::Z) =
if x<y
then (x # y)::mergePass(Z)
else (y # x)::mergePass(Z);
Edit: If mergePass is called on [[1,9],[7,8],[4,5],[6]] I will need it to return [[1,7,8,9],[4,5,6]].
This merge function takes two sorted lists
fun merge([],y) = y
| merge(x,[]) = x
| merge(a::x,b::y) =
if a < b then a::merge(x,b::y)
else b::merge(a::x,y);
You seem reasonably close. A few hints/remarks:
1) Aesthetically, using nil in one line and [] in others seems odd. Either use all nil or use all []
2) Since the input are lists of lists, in x::y::z, the identifiers x and y would be lists of integers, rather than individual integers. Thus, x<y wouldn't make sense. You can't compare lists of integers using <.
3) Your problem description strongly suggests that the inner-lists are all 1-element lists. Thus you could use the pattern [x]::[y]::z to allow you to compare x and y. In this case, x#y could be replaced by [x,y]
4) If the inner lists are allowed to be of arbitrary size, then your code needs major revision and would probably require a full-fledged sort function to sort the result of concatenating pairs of inner lists. Also, in this case, the single list in the one inner list case should probably be sorted.
5) You have a typo: mergeP isn't mergePass.
On Edit:
If the sublists are each sorted (and the name of the overall function perhaps suggests this) then you need a function called e.g. merge which will take two sorted lists and combine them into a single sorted list. If this is for a class and you have already seen a merge function as an example (perhaps in a discussion of merge-sort) -- just use that. Otherwise you will have to write your own before you write this function. Once you have the merge function, skip the part of comparing x and y and instead have something as simple as:
| mergePass (xs::ys::zss) = (merge xs ys) :: mergePass zss
If the sublists are not merged, then you will need a full-fledged sort in which case you would use something like:
| mergePass (xs::ys::zss) = sort(xs # ys) :: mergePass zss

Adding two lists together with map

So I'm trying to write some minimal code to put two lists of strings together, and to do this I thought it was best to use the haskell map function.
Essentially I want to be able to do adders ["1","2"] ["3","4"] = ["1","2","3","4"]
So I have a function called adder, which takes a list, then adds a string to that list and returns the new list. Then I have a function called adders which replicates the adder function, but adds a list of strings instead of just one string, however at the moment it produces multiple lists instead of one list.
I thought
adder :: [String] -> String -> [String]
adder y x = y ++ [x]
adders y x = map (adder y) x
would work, but this just gives a list of two lists
[["1","2","3"],[["1","2","4"]]
How is the best way to go about this?
I thought it was best to use the haskell map function
No. map f applies f to every element of your list. But you don't want to change the elements at all, you want to change the list itself. That, however, is out of scope of the things that are possible with map. map cannot add more elements, neither can it remove some.
If you want to concatenate two lists, simply use ++:
adders :: [a] -> [a] -> [a]
adders x y = x ++ y

How can I combine two lists by comparing elements in this way?

I'm just starting to learn Haskell, and I have to create a function composite that receives two lists a, b :: [(String, String)] as inputs, and outputs a new list c :: [(String, String)], which is a 'composition' of both a and b. Specifically, list c has to include only those pairs (p,q), where there is a r such that:
(p,r) is in a
(r,q) in in b
For example:
composite [("1","2")] [("2","3"), ("2","4")] == [("1","3"), ("1","4")]
composite [("1","2"), ("5","2")] [("2","3"), ("2","4")] == [("1","3"), ("1","4"), ("5","3"), ("5","4")]
composite [("1","2"), ("1","4"), ("1","5")] [("2","3"), ("4","3")] == [("1","3")]
How can I do this?
You can combine the lists using a list comprehension over multiple lists:
[(x,z)|(x,y) <- a, (y',z) <- b, y == y' ]
Note that the result is the list if (x,z) tuples, and the inputs are the lists of (x,y) and (y,z) tuples.
I have tried this in http://tryhaskell.org with your list test case; feel free to copy-paste it there and play around with it:
[(x,z) | (x,y) <-[('a', 'b'), ('a', 'd'), ('a', 'e')],(y',z) <- [('b','c'), ('d','c')], y == y']
This yields:
[('a','c'),('a','c')]
There are a few other things to note.
First, the y == y'. As #chi points out, if you use 'y' again in the list comprehension, the system does not consider it the same variable. You need to use a new variable, y' (or any other name) and explicitly tell Haskell that y and y' should have the same value.
Second, we're not using capitals; Haskell is case-sensitive and uses capitals for other purposes.
Third, you don't have to make it only for Strings. The function can operate on tuples of arbitrary types:
composite :: [(a,a)] -> [(a,a)] -> [(a,a)]
As #Daniel Wagner observes in the comments, it's actually a little more complicated:
composite :: (Eq a) => [(a,a)] -> [(a,a)] -> [(a,a)]
The Eq a tells Haskell that a is something that you can compare for equality. Formally, a is a member of the Eq type class.
He also observes that we can generalize this further: the lefthand side of the tuples in list A don't have to be of the same type as the righthand side of the tuples in list B. So you could have, for example, a list of (Int,String) and a list of (String,Char), and match them on the String. The type would become:
composite :: Eq b => [(a, b)] -> [(b, c)] -> [(a, c)]
A final thing to note is that there may be duplicates in your resulting list. This is the case in your third test case.
The exercise probably doesn't require you to remove the duplicates.. yet.
Haskells libraries provide tools to remove duplicates. In a production setting, you should use these tools. But when learning, writing your own code to remove duplicates may be a useful exercise.
I've also got it in ideone.org. Don't worry about the "main" and "print" over there for now; just experiment with the function and see if you understand it.
S.L. Barth is on the right track, but isn't quite there. What you need to do is to go through the cartesian product of both lists, compare the y parts and if they match, then you can emit a tuple on the output.
This can easily be done with a list comprehension, such as this one:
[(x, z) | (x, y1) <- a, (y2, z) <- b, y1 == y2]
You should be able to wrap this in a function.
Note that if you want the function to be polymorphic, the type of it needs an Eq y constraint so that you can actually compare the y parts:
composite :: Eq y => [(x, y)] -> [(y, z)] -> [(x, z)]

Difficulty thinking of properties for FsCheck

I've managed to get xUnit working on my little sample assembly. Now I want to see if I can grok FsCheck too. My problem is that I'm stumped when it comes to defining test properties for my functions.
Maybe I've just not got a good sample set of functions, but what would be good test properties for these functions, for example?
//transforms [1;2;3;4] into [(1,2);(3,4)]
pairs : 'a list -> ('a * 'a) list //'
//splits list into list of lists when predicate returns
// true for adjacent elements
splitOn : ('a -> 'a -> bool) -> 'a list -> 'a list list
//returns true if snd is bigger
sndBigger : ('a * 'a) -> bool (requires comparison)
There are already plenty of specific answers, so I'll try to give some general answers which might give you some ideas.
Inductive properties for recursive functions. For simple functions, this amounts probably to re-implementing the recursion. However, keep it simple: while the actual implementation more often than not evolves (e.g. it becomes tail-recursive, you add memoization,...) keep the property straightforward. The ==> property combinator usually comes in handy here. Your pairs function might make a good example.
Properties that hold over several functions in a module or type. This is usually the case when checking abstract data types. For example: adding an element to an array means that the array contains that element. This checks the consistency of Array.add and Array.contains.
Round trips: this is good for conversions (e.g. parsing, serialization) - generate an arbitrary representation, serialize it, deserialize it, check that it equals the original.
You may be able to do this with splitOn and concat.
General properties as sanity checks. Look for generally known properties that may hold - things like commutativity, associativity, idempotence (applying something twice does not change the result), reflexivity, etc. The idea here is more to exercise the function a bit - see if it does anything really weird.
As a general piece of advice, try not to make too big a deal out of it. For sndBigger, a good property would be:
let ``should return true if and only if snd is bigger`` (a:int) (b:int) =
sndBigger (a,b) = b > a
And that is probably exactly the implementation. Don't worry about it - sometimes a simple, old fashioned unit test is just what you need. No guilt necessary! :)
Maybe this link (by the Pex team) also gives some ideas.
I'll start with sndBigger - it is a very simple function, but you can write some properties that should hold about it. For example, what happens when you reverse the values in the tuple:
// Reversing values of the tuple negates the result
let swap (a, b) = (b, a)
let prop_sndBiggerSwap x =
sndBigger x = not (sndBigger (swap x))
// If two elements of the tuple are same, it should give 'false'
let prop_sndBiggerEq a =
sndBigger (a, a) = false
EDIT: This rule prop_sndBiggerSwap doesn't always hold (see comment by kvb). However the following should be correct:
// Reversing values of the tuple negates the result
let prop_sndBiggerSwap a b =
if a <> b then
let x = (a, b)
sndBigger x = not (sndBigger (swap x))
Regarding the pairs function, kvb already posted some good ideas. In addition, you could check that turning the transformed list back into a list of elements returns the original list (you'll need to handle the case when the input list is odd - depending on what the pairs function should do in this case):
let prop_pairsEq (x:_ list) =
if (x.Length%2 = 0) then
x |> pairs |> List.collect (fun (a, b) -> [a; b]) = x
else true
For splitOn, we can test similar thing - if you concatenate all the returned lists, it should give the original list (this doesn't verify the splitting behavior, but it is a good thing to start with - it at least guarantees that no elements will be lost).
let prop_splitOnEq f x =
x |> splitOn f |> List.concat = x
I'm not sure if FsCheck can handle this though (!) because the property takes a function as an argument (so it would need to generate "random functions"). If this doesn't work, you'll need to provide a couple of more specific properties with some handwritten function f. Next, implementing the check that f returns true for all adjacent pairs in the splitted lists (as kvb suggests) isn't actually that difficult:
let prop_splitOnAdjacentTrue f x =
x |> splitOn f
|> List.forall (fun l ->
l |> Seq.pairwise
|> Seq.forall (fun (a, b) -> f a b))
Probably the only last thing that you could check is that f returns false when you give it the last element from one list and the first element from the next list. The following isn't fully complete, but it shows the way to go:
let prop_splitOnOtherFalse f x =
x |> splitOn f
|> Seq.pairwise
|> Seq.forall (fun (a, b) -> lastElement a = firstElement b)
The last sample also shows that you should check whether the splitOn function can return an empty list as part of the returned list of results (because in that case, you couldn't find first/last element).
For some code (e.g. sndBigger), the implementation is so simple that any property will be at least as complex as the original code, so testing via FsCheck may not make sense. However, for the other two functions here are some things that you could check:
pairs
What's expected when the original length is not divisible by two? You could check for throwing an exception if that's the correct behavior.
List.map fst (pairs x) = evenEntries x and List.map snd (pairs x) = oddEntries x for simple functions evenEntries and oddEntries which you can write.
splitOn
If I understand your description of how the function is supposed to work, then you could check conditions like "For every list in the result of splitOn f l, no two consecutive entries satisfy f" and "Taking lists (l1,l2) from splitOn f l pairwise, f (last l1) (first l2) holds". Unfortunately, the logic here will probably be comparable in complexity to the implementation itself.