2
votes

Playing with a function based on an example in "Purescript by Example" ch 5 and am a bit stumped on how to declare polymorphic row types.

The following compiles fine

type Student = {
              first :: String,
              last :: String,
              class :: String
            }

type GymMember = {
              first :: String,
              last :: String,
              benchPressPB :: Int
            }

daveG :: GymMember
daveG = {
        first: "Dave",
        last: "Bro",
        benchPressPB: 300
    }

philS :: Student
philS = {
        first : "Dave",
        last : "Swat",
        class : "1A"
      }

 schoolRollName :: forall t15.
  { last :: String
  , first :: String
  | t15
  } -> String
 schoolRollName rec = rec.last <> ", " <> rec.first

firstAndSurname :: forall t82.
{ first :: String
, last :: String
| t82
}
-> String
firstAndSurname rec =  rec.first <> " " <> rec.last

daveFandS :: String
daveFandS = firstAndSurname daveG

daveSR :: String
daveSR = schoolRollName daveG

philFandS :: String
philFandS = firstAndSurname philS

philSR :: String
philSR = schoolRollName philS

But how do I remove the duplication in the type signatures of schoolRollName and firstAndSurname.

I thought the following would work but the types do not match up:

type NamedThing = forall t15.
                { last :: String
                , first :: String
                | t15
                }

schoolRollName :: NamedThing -> String
schoolRollName rec = rec.last <> ", " <> rec.first

firstAndSurname :: NamedThing -> String
firstAndSurname rec =  rec.first <> " " <> rec.last

-- !! Could not match type
daveFandS :: String
daveFandS = firstAndSurname daveG
1

1 Answers

5
votes

NamedThing isn't declared correctly. To match the type NamedThing you have to provide a value which does work forall possible records with at least a first and last field. Since daveG is not such a value the compiler complains - even further there is no value for such type.

Move the t to the type-alias:

type NamedThing t = {first :: String, last :: String | t}

Now firstAndSurname does have to provide a working function forall NamedThings with any extra fields. Simple solution:

firstAndSurname :: forall t. NamedThing t -> String
firstAndSurname rec =  rec.first <> " " <> rec.last

Finally the compiler is happy with that:

daveFandS :: String
daveFandS = firstAndSurname daveG