listhaskellcustom-data-type

Split list of student according to their mark - haskell


There is a list of students where

data Student = Student {
   name :: String,
   mark :: Mark
} deriving Show

data Mark = F|E|D|C|B|A deriving (Show, Eq, Ord)

I need to split it like that [(mark,[students with this mark])]

I made something like this:

splitToGroups :: [Student] -> [(Mark, [String])]    
splitToGroups [] = []
splitToGroups students = foldr funct [] students where
    funct student [] = [(mark student,[name student])]
    funct student ((x,xs):xss) | mark student == x = ((x,(name student):xs):xss)
                               | otherwise = (mark student,[name student]):(x,xs):xss

but it works incorectly. Maybe someone knows how it could be done..


Solution

  • Don't manually recurse if you can use standard tools. You can do this with sorting and grouping, but IMO preferrable is to use the types to express that you're building an associative result, i.e. a map from marks to students.

    import qualified Data.Map as Map
    
    splitToGroups :: [Student] -> Map.Map Mark [String]
    splitToGroups students = Map.fromListWith (<>)
         [ (sMark, [sName])
         | Student sName sMark <- students ]
    

    (If you want a list in the end, just use Map.toList.)