fork(1) download
  1. import Data.List
  2.  
  3. {-
  4. 車と人を重要の軽い順に順位をつけます。元のリストの順序は変更したくありません。
  5. ※ 人は未実装
  6. -}
  7.  
  8. {-
  9. 質問
  10. 1. makeCarRankingをHumanにも使えるように汎用的にするにはどうしたらいいか?
  11. 2. makeCarRankingのように全体を見てから全部の要素に値を設定する操作はどうしたらスマートか?
  12. -}
  13.  
  14. -- 車
  15. data Car = Car { carWeight :: Int, carRanking :: Int } deriving Show
  16. -- 人間
  17. data Human = Human { humanWeight :: Int, humanRanking :: Int } deriving Show
  18.  
  19. -- 車たち
  20. cars :: [Car]
  21. cars = [Car { carWeight = 10, carRanking = 0 }, Car { carWeight = 5, carRanking = 0 }, Car { carWeight = 20, carRanking = 0 }]
  22. -- 人たち
  23. humans :: [Human]
  24. humans = [Human { humanWeight = 10, humanRanking = 0 }, Human { humanWeight = 5, humanRanking = 0 }, Human { humanWeight = 20, humanRanking = 0 }]
  25.  
  26. -- 車たちに順位をつける
  27. makeCarRanking :: [Car] -> [Car]
  28. makeCarRanking xs = map (\c -> (snd c)) sortRanked
  29. where -- 順序を元に戻すためにインデックスを付加 [Car] -> [(index, Car)]
  30. zipped = zip [(1 :: Int)..] xs
  31. -- 重さでソートする
  32. sorted = sortBy (\(_, l) (_, r) -> compare (carWeight l) (carWeight r)) zipped
  33. -- ランキングを付加 [(index, Car)] -> [(ranking, (index, Car))]
  34. zipRanked = zip [(1 :: Int)..] sorted
  35. -- Carにランキングを設定 [(ranking, (index, Car))] -> [(index, Car)]
  36. ranked = map (\(r, (i, c)) -> (i, Car { carWeight = (carWeight c), carRanking = r })) zipRanked
  37. -- 元の順序に戻す
  38. sortRanked = sortBy (\(li, _) (ri, _) -> compare li ri) ranked
  39.  
  40. main = do
  41. putStrLn $ show $ makeCarRanking cars
Success #stdin #stdout 0s 4596KB
stdin
Standard input is empty
stdout
[Car {carWeight = 10, carRanking = 2},Car {carWeight = 5, carRanking = 1},Car {carWeight = 20, carRanking = 3}]