@@ -11,7 +11,7 @@ module Generics.Diff.Class
11
11
, gdiffWith
12
12
, eqDiff
13
13
, diffWithSpecial
14
- , specialDiffVia
14
+ , gspecialDiffNested
15
15
16
16
-- * Special case: lists
17
17
, diffListWith
20
20
21
21
import Data.SOP
22
22
import Data.SOP.NP
23
+ import qualified GHC.Generics as G
23
24
import Generics.Diff.Render
24
25
import Generics.Diff.Type
25
26
import Generics.SOP as SOP
27
+ import Generics.SOP.GGP as SOP
26
28
27
29
{- | A type with an instance of 'Diff' permits a more nuanced comparison than 'Eq' or 'Ord'.
28
30
If two values are not equal, 'diff' will tell you exactly where they differ ("in this contructor,
@@ -207,51 +209,44 @@ gdiffWithPure ::
207
209
DiffResult a
208
210
gdiffWithPure ds = gdiffWith $ cpure_POP (Proxy @ c ) ds
209
211
210
- {- | Helper function to implement 'specialDiff' for a type with @SpecialDiffError a = DiffErrorNested xss@.
212
+ {- | Helper function to implement 'specialDiff' for an instance of "GHC.Generic", with
213
+ @SpecialDiffError a = DiffErrorNested xss@.
211
214
212
215
For example, say we want to implement 'SpecialDiff' (and then 'Diff') for @Tree@ from @containers@.
213
216
We'd ideally like to use a 'SOP.Generic' instance, but we don't have one. Nevertheless we can fake one,
214
- by providing a function to convert from @Tree@ to what __would__ be its 'SOP.Rep', and a set of 'ConstructorInfo's
215
- which __would__ have been derived.
217
+ using 'G.Generic' from "GHC.Generics".
216
218
217
219
@
218
220
data Tree a = Node
219
221
{ rootLabel :: a
220
222
, subForest :: [Tree a]
221
223
}
222
-
223
- type TreeCode a = '[ '[a, [Tree a]]]
224
-
225
- fromTree :: Tree a -> 'NS' ('NP' 'I') (TreeCode a)
226
- fromTree (Node lbl frst) = 'Z' $ 'I' lbl ':*' 'I' frst ':*' 'Nil'
227
-
228
- treeCons :: 'NP' 'ConstructorInfo' (TreeCode a)
229
- treeCons = 'Record' "Node" ('FieldInfo' "rootLabel" ':*' 'FieldInfo' "subForest" ':*' 'Nil') ':*' 'Nil'
224
+ deriving ('G.Generic')
230
225
231
226
instance ('Diff' a) => 'SpecialDiff' (Tree a) where
232
- type 'SpecialDiffError' (Tree a) = 'DiffErrorNested' '[ '[a, [ Tree a]]]
233
- 'specialDiff' = 'specialDiffVia' fromTree treeCons
227
+ type 'SpecialDiffError' (Tree a) = 'DiffErrorNested' ('GCode' ( Tree a))
228
+ 'specialDiff' = 'gspecialDiffNested'
234
229
235
230
'renderSpecialDiffError' = 'diffErrorNestedDoc'
236
231
237
232
instance ('Diff' a) => 'Diff' (Tree a) where
238
233
diff = 'diffWithSpecial'
239
234
@
240
235
-}
241
- specialDiffVia ::
242
- forall a code .
243
- (All2 Diff code ) =>
244
- -- | Convert a type to an SOP representation
245
- ( a -> NS ( NP I ) code ) ->
246
- -- | Manual list of constructor info
247
- NP ConstructorInfo code - >
236
+ gspecialDiffNested ::
237
+ forall a .
238
+ ( G. Generic a
239
+ , GFrom a
240
+ , GDatatypeInfo a
241
+ , All2 Diff ( GCode a )
242
+ ) = >
248
243
a ->
249
244
a ->
250
- Maybe (DiffErrorNested code )
251
- specialDiffVia toCode constructors l r = gdiff' constructors differs (toCode l) (toCode r)
245
+ Maybe (DiffErrorNested ( GCode a ) )
246
+ gspecialDiffNested l r = gdiff' constructors differs (unSOP $ gfrom l) (unSOP $ gfrom r)
252
247
where
253
- differs :: NP (NP Differ ) code
254
248
differs = unPOP $ hcpure (Proxy @ Diff ) (Differ diff)
249
+ constructors = constructorInfo $ gdatatypeInfo $ Proxy @ a
255
250
256
251
------------------------------------------------------------
257
252
-- Auxiliary functions
0 commit comments