Вот как вы могли бы использовать комбинаторы семантического редактора (SEC), как предложил Lambdageek.
Сначала несколько полезных сокращений:
type Unop a = a -> a
type Lifter p q = Unop p -> Unop q
Здесь Unop
«семантический редактор», а Lifter
- комбинатор семантического редактора. Некоторые лифтеры:
onManager :: Lifter Coach BBTeam
onManager f (BBTeam n m p) = BBTeam n (f m) p
onDiet :: Lifter Diet Coach
onDiet f (Coach n c d) = Coach n c (f d)
onStakes :: Lifter Integer Diet
onStakes f (Diet n s e) = Diet n (f s) e
Теперь просто составите SEC, чтобы сказать, что вы хотите, а именно добавьте 1 к дозам диеты менеджера (команды):
addManagerSteak :: Unop BBTeam
addManagerSteak = (onManager . onDiet . onStakes) (+1)
. Сравнивая с подходом SYB, версия SEC требует дополнительной работы для определения SEC, и я только предоставил те, которые нужны в этом примере. SEC позволяет целевое приложение, которое было бы полезно, если бы у игроков были диеты, но мы не хотели их подстраивать. Возможно, есть хороший способ SYB справиться с этим различием.
Изменить: Вот альтернативный стиль для основных SEC:
onManager :: Lifter Coach BBTeam
onManager f t = t { manager = f (manager t) }