This question derived from previous question and answer. You can found the link here: Haskell :: Recursion in Recursion for Loop in Loop (Part 1)
The question were answered, I can say super amazing with nice explanation for future reference. Credit to @user2407038 for his amazing skills. However, something interesting to ponder with recursion with more than two partition. To make it clear I've changed the data a little bit for simplicity. Here how it looks:
Previously, the 2 red dots were generated by finding (min x, min y) and (max x, max y). To generate 4 red dots (min x, min y) (max x, min y) (min x, max y) (max x, max y) partition4 should take into consideration. Visually it looks like this:
Considering the max members for each group is 3, group 1 and group 4 exceed the number. A new group should be created based on these group. However, the trickier part is that this group will not compute the distance with previous red dots:
The edited code for previous question:
data Point = Point { ptX :: Double, ptY :: Double }
data Cluster = Cluster { clusterPts :: [Point] }
minMaxPoints :: [Point] -> (Point, Point)
minMaxPoints ps =
(Point minX minY
,Point maxX maxY)
where minX = minimum $ map ptX ps
maxX = maximum $ map ptX ps
minY = minimum $ map ptY ps
maxY = maximum $ map ptY ps
main = do
let pointDistance :: Point -> Point -> Double
pointDistance (Point x1 y1) (Point x2 y2) = sqrt $ (x1-x2)^2 + (y1-y2)^2
cluster1 :: [Point] -> [Cluster]
cluster1 ps =
let (mn, mx) = minMaxPoints ps
(psmn, psmx) = partition (\p -> pointDistance mn p < pointDistance mx p) ps
in [ Cluster psmn, Cluster psmx ]
cluster :: [Point] -> [Cluster]
cluster ps =
cluster1 ps >>= \cl@(Cluster c) ->
if length c > 5
then cluster c
else [cl]
testPts :: [Point]
testPts = map (uncurry Point)
[ (1,0), (2,1), (0,2)
, (5,2), (4,3), (4,4)
, (8,2), (9,3), (10,2)
, (11,4), (12,3), (13,3) ]
main = mapM (map (\p -> (ptX p, ptY p)) . clusterPts) $ cluster testPts
print main
I've found it when the length c changed the answer as not as expected it should be. Perhaps I've edited it wrongly (Sigh).
Still figuring how to fit in PartitionN code for partitioning into N groups as suggested.



Debug.Trace.traceor the GHCi debugger. You should be able to print each input that is passed toclusterand see if that's what you expect.partitionNpart of the question, just replacecluster1with the newcluster1function (of course you must also change the newcluster1and all related functions to usePointinstead of(Double, Double)). I recommend you try this yourself - it would be a good learning exercise.main = mapM ..) - in my previous answer, the code wasmapM_ (print . map (\p -> (ptX p, ptY p)) . clusterPts)- this function takes a list of clusters, converts each one to a list of tuples, and prints every list. The modified functionmapM (map .. . clusterPts)takes a list of clusters, converts them to lists of lists of tuples and computes the cartesian product(!). This can be reduced to the difference betweenmapM idandmapM print(try it on e.g.[[0,1],[2,3]]). Note in these two casesmapMis used at different types.