У меня есть эти типы данных:
data PointPlus = PointPlus
    { coords :: Point
    , velocity :: Vector
    } deriving (Eq)
data BodyGeo = BodyGeo
    { pointPlus :: PointPlus
    , size :: Point
    } deriving (Eq)
data Body = Body
    { geo :: BodyGeo
    , pict :: Color
    } deriving (Eq)
Это базовый тип данных для персонажей, врагов, объектов и т.д. в моей игре (ну, я просто имею два прямоугольника в качестве игрока и земли прямо сейчас: p).
Когда клавиша, символы перемещаются вправо, влево или прыгают, меняя ее velocity. Перемещение выполняется добавлением velocity в coords. В настоящее время он написан следующим образом:
move (PointPlus (x, y) (xi, yi)) = PointPlus (x + xi, y + yi) (xi, yi)
Я просто беру PointPlus часть моего Body, а не всего Body, иначе это будет:
move (Body (BodyGeo (PointPlus (x, y) (xi, yi)) wh) col) = (Body (BodyGeo (PointPlus (x + xi, y + yi) (xi, yi)) wh) col)
Лучше ли первая версия move? В любом случае, если move изменяет только PointPlus, должна существовать другая функция, которая вызывает его внутри нового Body. Я объясню: есть функция update, которая вызывается для обновления состояния игры; он передает текущее состояние игры, единственное Body на данный момент и возвращает обновленный Body.
update (Body (BodyGeo (PointPlus xy (xi, yi)) wh) pict) = (Body (BodyGeo (move (PointPlus xy (xi, yi))) wh) pict)
Это щекочет меня. Все сохраняется в пределах Body, кроме PointPlus. Есть ли способ избежать этой полной "реконструкции" вручную? Как в:
update body = backInBody $ move $ pointPlus body
Без определения backInBody, конечно.
