-
Notifications
You must be signed in to change notification settings - Fork 1
/
ToInstance01.hs
52 lines (40 loc) · 1.67 KB
/
ToInstance01.hs
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
41
42
43
44
45
46
47
48
49
50
51
52
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -fplugin Data.Constraint.Deriving #-}
{-# OPTIONS_GHC -fplugin-opt Data.Constraint.Deriving:dump-instances #-}
module Spec.ToInstance01 where
{-
This is a minimal example for deriving multiple instances
for a newtype over a type family.
The plugin provides two advantages over manually implementing instances using singletons:
* No need to implement every class function manually
* Instance elaboration at the call site happens only once for many used functions,
rather than once for every fuction usage.
-}
import Data.Constraint
import Data.Constraint.Deriving
import Data.Constraint.Unsafe
newtype Number t = Number (NumberFam t)
type family NumberFam t where
NumberFam Int = Int
NumberFam Double = Double
data NumberSing t where
NumInt :: NumberSing Int
NumDouble :: NumberSing Double
class KnownNumber t where numberSing :: NumberSing t
instance KnownNumber Int where numberSing = NumInt
instance KnownNumber Double where numberSing = NumDouble
{-# ANN deriveEq (ToInstance NoOverlap) #-}
deriveEq :: KnownNumber t => Dict (Eq (Number t))
deriveEq = deriveIt numberSing
{-# ANN deriveOrd (ToInstance NoOverlap) #-}
deriveOrd :: KnownNumber t => Dict (Ord (Number t))
deriveOrd = deriveIt numberSing
{-# ANN deriveNum (ToInstance NoOverlap) #-}
deriveNum :: KnownNumber t => Dict (Num (Number t))
deriveNum = deriveIt numberSing
deriveIt :: (c Double, c Int) => NumberSing t -> Dict (c (Number t))
deriveIt NumInt = mapDict (unsafeDerive Number) Dict
deriveIt NumDouble = mapDict (unsafeDerive Number) Dict