2015-11-21 4 views
5

Я пытаюсь перенести библиотеку из Elm 0.15 в 0.16. Механизм расширения записи удален.Альтернатива расширению записи Elm

My library предлагает физические вычисления на телах (представлены как записи) и использует расширение записи, чтобы пользователи могли добавлять метки и другие метаданные о телах.

Мои example code показывает это использование путем добавления метки для всех органов после их создания:

labeledBodies = map (\b -> { b | label = bodyLabel b.restitution b.inverseMass }) someBodies 

Этот список помеченных органов также передается в библиотеку:

main = Signal.map scene (run labeledBodies tick) 

Какие работы: hardcoding a meta параметр в Body вот так:

type alias Body a = { 
    pos: Vec2, -- reference position (center) 
    velocity: Vec2, -- direction and speed 
    inverseMass: Float, -- we usually use only inverse mass for calculations 
    restitution: Float, -- bounciness factor 
    shape: Shape, 
    meta: a 
} 

Но это делает API более неуклюжим, потому что он заставляет вспомогательные функции принимать дополнительный параметр. Есть ли более элегантный способ справиться с этим изменением?

+0

Действительно ли «метка» действительно необходима для записи? Не могли бы вы вместо этого вызвать 'bodyLabel' из функции' run'? –

+0

В этом случае да (но это будет дополнительная работа, выполняющая это каждый раз), но в общем случае нет: я хочу иметь возможность отслеживать и другие метаданные, которые не зависят от тела (например, hitpoints, unique id, что угодно) –

ответ

1

Что делать, если поле meta имело тип Dict String String? Тогда вам не придется делать какие-либо сумасшедшие переменные типа неуклюжими. Однако вы теряете гарантии, что все записи, которые вы передаете, действительно имеют ярлыки, поэтому вам нужно работать с Maybe String, когда вы делаете Dict.get "label" r.meta.

+0

Я действительно рассматривал возможность добавления поля для фиксированного id или метаданных, но это не так хорошо работает для общего случая, когда я не хочу отслеживать только значения String. –

1

Как насчет того, чтобы использовать маркированный тип объединения?

type BodyWithMeta = 
    LabeledBody Body String 

labeledBodies = map (\b -> LabeledBody b (bodyLabel b.restitution b.inverseMass)) someBodies 
+0

Возможно, это не совсем ясно из вопроса. Но я хочу, чтобы функция «run» не потеряла связь между телом и прикрепленными метаданными. С вашим предложением «run» должен был знать тип «LabeledBody», в то время как я надеялся сохранить общий метаданные. –

+0

'' '' 'нужно этикетке вообще? – robertjlooby

+0

'run' не нуждается в нем (он ничего не знает об этом), но он должен быть частью структуры данных, которая' run' работает с –