[ФЯ] вычисления с состоянием

Landstreicher

Необходимо смоделировать поведение некоторой системы, имеющей сложное состояние. Допустим, оно состоит из трех компонент X, Y, Z.
Я знаю несколько способов:
1. Чисто функциональный подход:
type ObjState = (X, Y, Z)
evolve :: State -> State
2. Монады:
type ObjState = (X, Y, Z)
evolve :: State ObjState
3. Монады, по каждому компоненту отдельно:
evolve :: StateT X StateT Y State Z
Общая проблема во всех случаях такая. Допустим, в состояние добавляется новый элемент, скажем W.
Тогда приходится менять весь код. Например:
1-ый способ:
evolve (x,y,z) = (x+1,y-2,z) меняется на evolve(x,y,z,w) = (x+1,y-2,z,w)
2-ой способ:
evolve = do { (x,y,z) <- get; put (x+1, y-2, z); } меняется на evolve = do { (x,y,z,w <- get; put (x+1, y-2, z, w) }
3-ий способ
нужно вставлять дополнительные lift (в данном случае не надо, т.к. вставка в конец, но в общем случае --- надо).
1-ый подход слабо применим, так как состояние достаточно сложное и эволюция объекта представляет собой комбинацию множества функций, каждая из которых меняет один-два компонента. Протаскивать все состояние через все функции не представляется осмысленным.
Вопрос: как сделать так, чтобы при добавлении нового компонента в состояние объем изменений не зависел от количества уже имеющегося кода? Какие на ваш взгляд плюсы и минусы перечисленных способов?
Примечание: в ИЯ данная задача решается тривиально:
class Obj {
int x;
double y;
string z;
}
Obj::evolve {
x += 1; // этот код не требует изменений при добавлении нового поля w
y -= 2;
}

Marinavo_0507

открой для себя другие структуры данных, кроме кортежей
например, записи в ocaml подойдут, да и объекты
разветвлённые деревья тоже - если каждая функция со своей веткой работает
в более динамических случаях - ассоциативные массивы всякие
про использование абстракции данных не надо напоминать, надеюсь?

Ivan8209

Не знаю, как в ML-семействе с насыщением полей, но наверняка как-то это делают.
Если использовать слабые языки (например, лисп-семейства) и правильно писать, то есть точно тот же способ, что и твой "в ИЯ."
А так, есть
4. type newstate = (oldstate, added);
т.е. через композицию.
Недостаток: всё равно надо написать "evolve oldstate".
---
...Я работаю антинаучным аферистом...

Ivan8209

Про ассоциативные списки я тоже подумал,
не знаю, насколько они распространены в МЛ-семействе,
если не заботиться о скоростях, то да, очень удобно.
Но это надо сразу так писать.
---
...Я работаю антинаучным аферистом...
Оставить комментарий
Имя или ник:
Комментарий: