2015-07-02 12 views
1

Я пишу описание сети для логики списка.
Это действительно просто: у меня есть поведение для текущего выбранного элемента (Maybe), и я хочу, чтобы всякий раз, когда пользователь добавляет новый элемент в список, текущий выбранный элемент будет выбирать только что созданное значение.Как узнать, что изменило поведение?

Пользователь также может удалять элементы из списка и вызывать различные другие изменения, поэтому я должен знать, когда создается новый элемент; Я не могу просто выбрать последний элемент при каждом изменении.

Я действительно не имею никакого кода, чтобы показать это, потому что все мои размышления о том, что делать даже не может быть написано с API *, но у меня есть контекст Frameworks t и (упрощенно):

bDb :: Behavior t [Entry] -- Created with accumB. 
bSelected :: Behavior t (Maybe Entry) -- Created with accumB. 
eAddEntry :: Event t() -- User clicked an add button. Created with fromAddHandler. 

* Ну, я подумал об использовании eAddEntry, чтобы выбрать последнюю запись, но это так плохо и даже если это будет работать, это просто гонка между добавлением нового элемента и его выбором.

Как я могу это сделать?

+0

Не могли бы вы просто умножить свой '[Entry]' на что-то еще в своем 'accB', которое сообщает вам источник последнего изменения? Таким образом, вы получите '([Entry], ReasonItChanged)' с некоторыми данными соответствующего типа данных ReasonItChanged = UserAdded | UserRemoved'. – Cactus

+0

@Cactus Err .. ну, я действительно хотел избежать добавления этой сложности, но если FRP/реактивный банан не имеет лучшего способа, я прибегу. Я попробую все же. Большое спасибо. – MasterMastic

+1

Вы просмотрели пример [CRUD.hs] (https://wiki.haskell.org/Reactive-banana/Examples#crud)? Это касается аналогичной ситуации. Идея состоит в том, что текущий выбранный элемент исходит из двух источников: пользователь нажимает кнопку в списке и изменяется в пределах программы. Самый простой способ сделать это - относиться к последнему как к «предложениям», а к первому - «окончательному». –

ответ

2

Я дал предложение Cactus в комментариях попробовать, и выясняется, что это невозможно сделать (мне нужно было бы связать changes в середине let блок, где поведение выбора и поведение списка, но они зависят друг от друга).

Итак, я решил начать все сначала с нуля, но на этот раз переделать, и обернуть все состояние в своем собственном типе данных, который сеть будет просто управлять. Так что действительно вся сеть будет выполнять функции вызова в сети в соответствии с событиями, и все. Получилось много превосходного imo, потому что нет беспорядочного аппликативного стиля, вся функциональность на самом деле просто простые функции, и это более модульная (я мог бы решить просто не использовать FRP вообще, и изменения были бы крайне незначительными - - просто переключите стрельбу с помощью функций, хотя мне все равно придется найти, где поставить состояние, которое, вероятно, было бы чем-то нечистым, как IORef).

Это настолько чистый, он выглядит что-то похожее на это:

data DbState = DbState Database SelectedItem LastAction Etc Etc 
emptyState :: DbState 
stateRemove, stateAdd :: DbState -> DbState 

и поведение просто:

let bDb = accumB emptyState $ unions 
     [stateAdd <$ eAddEntry 
     ,stateRemove <$ eRemoveEntry 
     ] 

До, я длина линии заполнены лямбды, <$>, <*> и т.д. . повсюду.

И теперь я просто rectimate' и вижу изменения через это LastAction.
Я также добавил проверку ошибок чрезвычайно тривиально.