Полиморфизм строк в Purescript. Какой правильный синтаксис?

Играя с функцией на основе примера из «Purescript by Example», глава 5, я немного озадачен тем, как объявлять полиморфные типы строк.

Следующие компилируются нормально

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

Но как мне убрать дублирование в сигнатурах типов schoolRollName и firstAndSurname.

Я думал, что следующее сработает, но типы не совпадают:

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

person John Walker    schedule 09.12.2016    source источник


Ответы (1)


NamedThing объявлен неправильно. Чтобы соответствовать типу NamedThing, вы должны предоставить значение, которое действительно работает для всех возможных записей, по крайней мере, с первым и последнее поле. Поскольку daveG не является таким значением, компилятор жалуется - даже больше нет значения для такого типа.

Переместите t на псевдоним типа:

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

Теперь firstAndSurname действительно должен предоставлять рабочую функцию forall NamedThings с любыми дополнительными полями. Простое решение:

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

Наконец, компилятор этим доволен:

daveFandS :: String
daveFandS = firstAndSurname daveG
person pete    schedule 09.12.2016