aboutsummaryrefslogtreecommitdiff
path: root/ch13_13.2-i.hs
blob: acce2b2ff4d6be732b446eaf65bd631da39e3765 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
{-# LANGUAGE ImportQualifiedPost #-}

-- Exercise 13.2-i
-- Provide a generic instance for the `Ord` class.

import GHC.Generics qualified as G

class GOrd a where
  gcompare :: a x -> a x -> Ordering

instance GOrd G.U1 where
  gcompare G.U1 G.U1 = EQ

instance GOrd G.V1 where
  gcompare _ _ = EQ

instance Ord a => GOrd (G.K1 _1 a) where
  gcompare (G.K1 a) (G.K1 b) = compare a b

instance (GOrd a, GOrd b) => GOrd (a G.:+: b) where
  gcompare (G.L1 a1) (G.L1 a2) = gcompare a1 a2
  gcompare (G.R1 b1) (G.R1 b2) = gcompare b1 b2
  gcompare (G.L1 _) (G.R1 _) = LT
  gcompare (G.R1 _) (G.L1 _) = GT

instance (GOrd a, GOrd b) => GOrd (a G.:*: b) where
  -- Don't forget `Ord` is a monoid! :)
  gcompare (a1 G.:*: b1) (a2 G.:*: b2) = gcompare a1 a2 <> gcompare b1 b2

instance GOrd a => GOrd (G.M1 _x _y a) where
  gcompare (G.M1 a1) (G.M1 a2) = gcompare a1 a2

genericCompare :: (G.Generic a, GOrd (G.Rep a)) => a -> a -> Ordering
genericCompare a b = gcompare (G.from a) (G.from b)

-- Example usage:
data Foo a b c = F0 | F1 a | F2 b c deriving (Eq, G.Generic)

instance (Ord a, Ord b, Ord c) => Ord (Foo a b c) where
  compare = genericCompare