# 21-Row-Example.purs

``````module TLP.RowExample where

import Prelude
import Effect (Effect)
import Effect.Console (log)
import Prim.Row (class Union, class Nub, class Cons)
import Type.Proxy (Proxy(..))

{-
`f` does the following type-level computation:
- combine two rows using union
- add another field using cons (age :: Int)
- remove a duplicate field using Nub
- union the result with something else                                    -}
f :: forall row1 row2 row1And2 row1And2PlusAge nubbedRow1And2PlusAge finalRow.
Union row1 row2 row1And2 =>
Cons "age" Int row1And2 row1And2PlusAge =>
Nub row1And2PlusAge nubbedRow1And2PlusAge =>
Union nubbedRow1And2PlusAge (otherField :: String) finalRow =>

Proxy row1 -> Proxy row2 -> Proxy finalRow
f _ _ = Proxy

first :: Proxy (name :: String, age :: Int)
first = Proxy

second :: Proxy (pets :: Array Pet)
second = Proxy

-- A function that can change what the outputted Record type must be
-- based on the row type it receives.
g :: forall finalRow a. Proxy finalRow -> a -> (a -> Record finalRow) -> Record finalRow
g _ a function = function a

-- Same thing as `g` but uses shorter type names and the shorter Record syntax
z :: forall r        a. Proxy r        -> a -> (a -> { | r }        ) -> { | r }
z _ a function = function a

main :: Effect Unit
main = do
-- These examples show that the type of the returned record differs
-- depending on what the two rows we pass to `f` are
log \$ show \$ g (f first second) 5
(\five -> { age: five, name: "John", pets: [Pet], otherField: "other"})

log \$ show \$ g (f first (Proxy :: Proxy (singlePet :: Pet))) 5
(\five -> { age: five, name: "John", singlePet: Pet, otherField: "other"})

-- These examples show that the output is the same regardless of
-- whether we use the short/long Record syntax
-- in our function's type signature.
log \$ show \$ g (Proxy :: Proxy (name :: String)) 5 (\five -> { name: "a " <> show five })
log \$ show \$ z (Proxy :: Proxy (name :: String)) 5 (\five -> { name: "a " <> show five })

-- needed to compile

data Pet = Pet
instance Show Pet where
show _ = "Pet"
``````