I want to write a function that takes in a sequence <1,1,2,2,3> and returns the sequence with equal elements grouped like <<1,1>, <2,2>, <3>>.
I\'m u
In Haskell you have group and groupBy. They're made with a helper function called span. Standard ML unfortunately does not have as rich a standard library, so you'll have to create the function yourself. But you could use the same approach:
Define a function span
that splits a list in two where the first part is the longest prefix for which some predicate is true, and the second part is the remainder of the list.
fun span p [] = ...
| span p (x::xs) = ... if p x then ... else ...
For example,
- span (fn n => n <= 3) [2,3,4,1,5]
> val it = ([2,3], [4,1,5])
This is a little difficult because you must somehow add x
to the result of calling span p xs
recursively, even though it returns a pair of lists; so you cannot just write x :: span p xs
; you have to unpack the pair that is returned and return (x :: ys, zs)
or (ys, x :: zs)
(and stop recursing once p x
is false).
Define a function groupBy
that uses span
. The function that groupBy
uses should have two arguments unlike in span
where p
took one argument: The first one is the element with which to group, and the second is the subsequent elements.
fun groupBy f [] = ...
| groupBy f (x::xs) = ... use span, f, x and xs to create (ys, zs) ...
... ys is the first group ...
... groupBy f zs is the remaining groups ...
Here it helps if the function f
is curried, i.e. has type
'a -> 'a -> bool
since then it can be used like val (ys, zs) = span (f x) xs
.
Feel free to ask follow-up questions if you want to use this approach.