Записи в PureScript не совпадают с записями в Haskell.
Haskell не имеет реальных записей, как их понимают в большинстве других языков.Записи Haskell - это просто способ определить функции доступа для полей ADT.Например, следующие два типа почти эквивалентны:
data A = A Int String
data B = B { x :: Int, y :: String }
За исключением того, что тип B
поставляется с предопределенными функциями доступа x :: B -> Int
и y :: B -> String
.
PureScript, с другой стороныУ него были реальные, специальные, полиморфные, расширяемые записи, которые сами по себе.Запись в PureScript определяется следующим образом:
{ x :: Int, y :: String }
Правильно, нет необходимости в data
или чем-либо еще.Записи просто случайные, вроде как кортежи в Haskell.Например:
getX :: { x :: Int, y :: String } -> Int
getX r = r.x
Конечно, если вы хотите, вы можете объявить псевдоним для своей записи, так же, как вы можете сделать это с любым другим типом:
type XY = { x :: Int, y :: String }
getX :: XY -> Int
getX = r.x
Вы также можетеиспользуйте запись в качестве члена ADT - опять же, как и любой другой тип:
data XYWrapped = XYWrapped { x :: Int, y :: String }
Но если вы сделаете это, вам понадобится развернуть ADT с помощью сопоставления с образцом, чтобы получить запись,Опять же, как и с любым другим типом:
getXWrapped :: XYWrapped -> Int
getXWrapped (XYWrapped r) = r.x
Вы не ограничены упаковкой только одной записи (как вы уже догадались: как и с любым другим типом):
data XYPQ = XYPQ { x :: Int, y :: String } { p :: Char, q :: Int }
getXPlusQ :: XYPQ -> Int
getXPlusQ (XYPQ a b) = a.x + b.q
Вооружившись этим знанием, теперь вы можете видеть, что ваши типы Point
и Rect
на самом деле не являются записями, а скорее ADT, которые переносят одну запись (и из-за этогоони должны быть newtype
с).
Вот почему вы получаете несоответствие типов.Поскольку вы написали r.upperLeft
, компилятор сделал вывод, что r
должна быть записью, содержащей поле с именем upperLeft
, но ваша подпись типа говорит, что r
имеет тип Rect
, который не является записью ввсе.Таким образом, компилятор жалуется.
Чтобы исправить это, вы можете либо переопределить ваши типы как фактические записи:
type Point = {
x :: Int,
y :: Int
}
type Rect = {
upperLeft :: Point,
upperRight :: Point,
lowerLeft :: Point,
lowerRight :: Point
}
, либо вы можете сделать так, чтобы ваша функция развернула ADT:
rectsOverlap (Rect r) (Rect s) =
let (Point rUpperRight) = r.upperRight
(Point rUpperLeft) = r.upperLeft
....
что было бы довольно утомительно.Поэтому я остановлюсь на первом варианте.
Обратите также внимание, что, как упоминалось выше, записи PureScript могут быть полиморфными и расширяемыми посредством полиморфизма.Подробнее об этом см. этот ответ .