Partition a list into equivalence classes

老子叫甜甜 提交于 2020-01-05 06:50:52

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!