@@ -222,18 +222,23 @@ type family KeyDoesNotExist (l :: Symbol) (lts :: [*]) :: Constraint where
223 KeyDoesNotExist q (l := t ': lts) = KeyDoesNotExist q lts
223 KeyDoesNotExist q (l := t ': lts) = KeyDoesNotExist q lts
225+type family Reverse (xs :: [*]) where
227+ Reverse (x ': xs) = RecAppend (Reverse xs) '[x]
225type family Insert (a :: *) (xs :: [*]) where
229type family Insert (a :: *) (xs :: [*]) where
226− Insert (a := t) '[] = a := t ': '[]
230+ Insert x '[] = x ': '[]
227− Insert (a := t1) (a := t2 ': xs) = a := t1 ': xs
231+ Insert (a := v) (a := _ ': xs) = a := v ': xs
228− Insert (a := t1) (x := t2 ': xs) = x := t2 ': Insert (a := t1) xs
232+ Insert a (x ': xs) = x ': Insert a xs
230type family Union xs ys where
234type family Union xs ys where
231 Union xs '[] = xs
235 Union xs '[] = xs
232 Union xs (y := t ': ys) = Union (Insert (y := t) xs) ys
236 Union xs (y := t ': ys) = Union (Insert (y := t) xs) ys
238+-- TODO: Rename to `Append`, because it just deals with general type list?
234type family RecAppend lhs rhs where
239type family RecAppend lhs rhs where
235 RecAppend '[] rhs = rhs
240 RecAppend '[] rhs = rhs
236− RecAppend (x := t ': xs) rhs = x := t ': RecAppend xs rhs
241+ RecAppend (x ': xs) rhs = x ': RecAppend xs rhs
238type family RecSize (lts :: [*]) :: Nat where
243type family RecSize (lts :: [*]) :: Nat where
239 RecSize '[] = 0
244 RecSize '[] = 0
@@ -394,9 +399,7 @@ combine lts rts =
394 (# s''''#, a# #) -> (# s''''#, MkRec a# #)
399 (# s''''#, a# #) -> (# s''''#, MkRec a# #)
395{-# INLINE combine #-}
400{-# INLINE combine #-}
397−-- | Union two records
402+-- | Union two records (left-biased)
399−-- NOTE: changed from original superrecord to not require a 'Sort'
401 forall lhs rhs res.
404 forall lhs rhs res.
402 ( KnownNat (RecSize lhs),
405 ( KnownNat (RecSize lhs),
@@ -426,6 +429,37 @@ union lts rts =
426 (# s''''#, a# #) -> (# s''''#, MkRec a# #)
429 (# s''''#, a# #) -> (# s''''#, MkRec a# #)
427{-# INLINE union #-}
430{-# INLINE union #-}
434+-- Insert at beginning, unless the field already exists, in which case set it
438+ ( KnownNat (RecSize rhs),
439+ KnownNat (RecSize res),
440+ res ~ Reverse (Insert (l := v) (Reverse rhs)),
441+ RecCopy '[l := v] '[l := v] res,
447+insert (l := v) rts =
449+ fromIntegral $ natVal' (proxy# :: Proxy# (RecSize res))
452+ case newSmallArray# size# (error "No value") s# of
454+ case recCopyInto (Proxy :: Proxy rhs) rts (Proxy :: Proxy res) arr# s'# of
456+ case recCopyInto (Proxy :: Proxy '[l := v]) (unsafeRCons (l := v) $ unsafeRNil 1) (Proxy :: Proxy res) arr# s''# of
458+ case unsafeFreezeSmallArray# arr# s'''# of
459+ (# s''''#, a# #) -> (# s''''#, MkRec a# #)
460+{-# INLINE insert #-}
430-- | Alias for 'combine'
464-- | Alias for 'combine'