问题
I am trying to write a function in SML which when given a list of general elements, reorders its elements into equivalent classes and returns a list of these classes (type "a list list). Leave the elements in the classes in the same order as in the original list. A given function defines the equivalence of the elements and it returns true if the elements are equivalent or false otherwise. I cannot seem to get a grip on the solution.
fun sample x y = x = y
Required type: fn : (''a -> ''a -> bool) -> ''a list -> ''a list list
Thank you very much for the help.
The helper function does not work correctly, all I want to do with it is see if a given element belongs to any of the classes and put it accordingly inside or create a new sublist which contains it.
fun srt listoflists func new =
case listoflists of [] => [[]]
| a::b => if func (new, hd a) = true then (new::a)::b
else if func (new, hd a) = false then a::(srt b func new) else [new]::a::b
The sample functions checks equivalence of two elements when divided by 11.
Tests are not all working, it is not adding 17 into a new class.
srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 7;
val it = [[7,7,7,7],[5,5,5],[11,11,11],[13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 5;
val it = [[7,7,7],[5,5,5,5],[11,11,11],[13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 11;
val it = [[7,7,7],[5,5,5],[11,11,11,11],[13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 13;
val it = [[7,7,7],[5,5,5],[11,11,11],[13,13,13,13]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13]] eq 17;
val it = [[7,7,7],[5,5,5],[11,11,11],[13,13,13],[]] : int list list
- srt [[7,7,7],[5,5,5],[11,11,11],[13,13,13],[111,111,111]] eq 111;
val it = [[7,7,7],[5,5,5],[11,11,11],[13,13,13],[111,111,111,111]]
How to correct this and also once this helper function works, how to encorporate it exactly into the main function that is required.
Thank you very much.
回答1:
Your example code seems like you are getting close, but has several issues
1) The basis cases is where new
should be added, so in that case you should return the value [[new]]
rather than [[]]
2) Your problem description suggests that func
be of type ''a -> ''a -> bool
but your code for srt
seems to be assuming it is of type (''a * ''a) -> bool
. Rather than subexpressions like func (new, hd a)
you need func new (hd a)
(note the parentheses location).
3) if func
returns a bool
then comparing the output to true
is needlessly verbose, instead of if func new (hd a) = true then ...
simply have if func new (hd a) then ...
4) Since you are adding [new]
in the basis cases, your second clause is needlessly verbose. I see no reason to have any nested if
expressions.
Since this seems to be homework, I don't want to say much more. Once you get the helper working correctly it should be fairly straightforward to use it (in the recursive case) of the overall function. Note that you could use (a @ [new])::b
rather than (new::a)::b
if you want to avoid the need for a final mapping of rev
across the final return value. @
is more expensive than ::
(it is O(n)
rather than O(1)
), but for small examples it really doesn't matter and could even be slightly better since it would avoid the final step of reversing the lists.
来源:https://stackoverflow.com/questions/40577169/partition-a-list-into-equivalence-classes