@@ -4,12 +4,16 @@ module Data.Record
44 , modify
55 , insert
66 , delete
7+ , equal
8+ , class EqualFields
9+ , equalFields
710 ) where
811
912import Data.Function.Uncurried (runFn2 , runFn3 )
1013import Data.Record.Unsafe (unsafeGetFn , unsafeSetFn , unsafeDeleteFn )
11- import Data.Symbol (class IsSymbol , SProxy , reflectSymbol )
12- import Type.Row (class RowLacks )
14+ import Data.Symbol (class IsSymbol , SProxy (..), reflectSymbol )
15+ import Prelude (class Eq , (&&), (==))
16+ import Type.Row (class RowLacks , class RowToList , Cons , Nil , RLProxy (RLProxy), kind RowList )
1317
1418-- | Get a property for a label which is specified using a value-level proxy for
1519-- | a type-level string.
@@ -109,3 +113,31 @@ delete
109113 -> Record r2
110114 -> Record r1
111115delete l r = runFn2 unsafeDeleteFn (reflectSymbol l) r
116+
117+ -- | Check two records of the same type for equality.
118+ equal
119+ :: forall r rs
120+ . RowToList r rs
121+ => EqualFields rs r
122+ => Record r
123+ -> Record r
124+ -> Boolean
125+ equal a b = equalFields (RLProxy :: RLProxy rs ) a b
126+
127+ class EqualFields (rs :: RowList ) (row :: # Type ) | rs -> row where
128+ equalFields :: RLProxy rs -> Record row -> Record row -> Boolean
129+
130+ instance equalFieldsCons
131+ ::
132+ ( IsSymbol name
133+ , Eq ty
134+ , RowCons name ty tailRow row
135+ , EqualFields tail row
136+ ) => EqualFields (Cons name ty tail ) row where
137+ equalFields _ a b = get' a == get' b && equalRest a b
138+ where
139+ get' = get (SProxy :: SProxy name )
140+ equalRest = equalFields (RLProxy :: RLProxy tail )
141+
142+ instance equalFieldsNil :: EqualFields Nil row where
143+ equalFields _ _ _ = true
0 commit comments