module Prairie.Zip where

import Prairie.Class
import Prairie.Fold

-- | Take two records and zip them together with the provided function.
--
-- The field is given for the final parameter in the function, allowing you to use @LambdaCase@.
--
-- @
-- zipWithRecord
--     (\a b ->
--         \case
--             UserName ->
--                 a <> b
--             UserAge ->
--                 a + b
--     )
-- @
--
-- @since 0.0.4.0
zipWithRecord
    :: forall rec. (Record rec)
    => (forall ty. ty -> ty -> Field rec ty -> ty)
    -> rec
    -> rec
    -> rec
zipWithRecord :: forall rec.
Record rec =>
(forall ty. ty -> ty -> Field rec ty -> ty) -> rec -> rec -> rec
zipWithRecord forall ty. ty -> ty -> Field rec ty -> ty
k rec
r0 rec
r1 =
    (forall ty. ty -> rec -> Field rec ty -> rec) -> rec -> rec -> rec
forall rec r.
Record rec =>
(forall ty. ty -> r -> Field rec ty -> r) -> r -> rec -> r
foldRecord ty -> rec -> Field rec ty -> rec
forall ty. ty -> rec -> Field rec ty -> rec
f rec
r0 rec
r0
  where
      f :: ty -> rec -> Field rec ty -> rec
      f :: forall ty. ty -> rec -> Field rec ty -> rec
f ty
v0 rec
rec Field rec ty
field =
          let v1 :: ty
v1 = Field rec ty -> rec -> ty
forall rec ty. Record rec => Field rec ty -> rec -> ty
getRecordField Field rec ty
field rec
r1
           in Field rec ty -> ty -> rec -> rec
forall rec ty. Record rec => Field rec ty -> ty -> rec -> rec
setRecordField Field rec ty
field (ty -> ty -> Field rec ty -> ty
forall ty. ty -> ty -> Field rec ty -> ty
k ty
v0 ty
v1 Field rec ty
field) rec
rec