是否可以手动更新行为的值? (函数式反应式编程,Threepenny)
Is it possible to manually update the value of a Behaviour? (Functional Reactive Programming, Threepenny)
我真希望我没有走入死胡同。我有一个行为,它给出当前选择的颜色和当前鼠标坐标,然后在单击鼠标时执行任务。该任务涉及查看列表,然后更新该列表中的值,以便稍后检索。我可以“存储”所选颜色这一事实让我希望可以用类似的方式存储列表。我正处于死胡同,不知道如何解决这个问题。非常感谢您的帮助。
-- There is a Blue button and a Red button on our UI. Whichever
-- button was clicked last is our current color selection.
colorRedSelected = const ColorRed <$ UI.click redButton
colorBlueSelected = const ColorBlue <$ UI.click blueButton
-- we combine both the above Events to create a new one that tells us the current selected color
colorSelected = unionWith const colorRedSelected colorBlueSelected
-- accumulate values for our Behaviour, starting with ColorRed selected by default
colorMode <- accumB ColorRed modeEvent
-- create a Behaviour
mouseCoordinate <- stepper (0,0) $ UI.mousemove canvas
-- want to start with the list [1,2,3,4], but this value should change later.
-- I have 'never' here, as I don't know what else to put here yet.
listState <- accumB ([1,2,3,4]) never
-- Combine the Behaviours, we now have a tuple (chosenColorMode, mouseCoordinateTuple, savedList)
let choices = (,,) <$> colorMode <*> mouseCoordinate <*> listState
-- Apply the event (of the user clicking the canvas) to the Behaviour,
-- creating a new Event that returns the above tuple when it fires
makeChoice = choices <@ UI.click canvas
onEvent makeChoice $ \(colorMode, (x,y), savedList) -> do
...
-- in this block we use the savedList, and generate a newList.
-- I want to update the choicePosition behaviour so that the newList
-- replaces the old savedList.
完全归功于 ,我将简单介绍一下它是如何解决的:
假设我们有一个函数可以根据某些值以某种方式修改列表。 How/why updateMyList
修改列表对于这个解释并不重要,我们只需要知道它的类型。对于这个例子,我们将决定列表如何变化的值是鼠标坐标元组 (x, y),我们将其作为第一个参数传递:
updateMyList :: (Double, Double) -> [Integer] -> [Integer]
updateMyList (x, y) oldList = ...
如果我们有一个事件告诉我们用户单击时的鼠标坐标:
mouseCoords :: Behavior (Double, Double)
mouseCoords <- stepper (0,0) $ UI.mousemove canvas
mouseClicked :: Event (Double, Double)
mouseClicked = mouseCoords <@ UI.click canvas -- this is the Event we need
我们需要做的是 fmap
列表更新功能到 mouseClicked
:
listChangeEvent = fmap updateMyList mouseClicked
所以我们创建了一个新的事件:当mouseClicked
被触发时,鼠标坐标作为第一个参数传递给updateMyList
,并且这是我们在那个时间戳的新事件的价值。但这是一个部分应用的函数,updateMyList
仍然需要一个 [Integer]
作为参数,因此,listChangeEvent
具有以下类型:
listChangeEvent :: Event ([Integer] -> [Integer])
现在,这是聪明的部分:如果我们使用 accumB
并指定起始累加器(即我们的起始列表,[1,2,3,4]
),然后还使用上面的 listChangeEvent
因为事件 accumB
的值来自:
listState <- accumB ([1,2,3,4]) listChangeEvent
那么那个累加器就是将被传递给Event ([Integer] -> [Integer])
中的函数的东西。这意味着 listChangeEvent
第一次触发时,updateMyList
将被调用:
updateMyList (x, y) [1,2,3,4] -- (x, y) being the mouse coordinates at that time
并且其结果成为 listState
中的 new 累加器值,并且该新列表将用作下一个 updateMyList
的参数时间listChangeEvent
触发器,依此类推。
我们可以将它用于任何事情,它不一定是我们要修改的列表。这只是为我们提供了一种使用值初始化 Behavior 的方法,并且我们可以通过创建等同于 updateMyList
.
的函数来准确指定 Behavior 的下一个值是如何导出的。
我真希望我没有走入死胡同。我有一个行为,它给出当前选择的颜色和当前鼠标坐标,然后在单击鼠标时执行任务。该任务涉及查看列表,然后更新该列表中的值,以便稍后检索。我可以“存储”所选颜色这一事实让我希望可以用类似的方式存储列表。我正处于死胡同,不知道如何解决这个问题。非常感谢您的帮助。
-- There is a Blue button and a Red button on our UI. Whichever
-- button was clicked last is our current color selection.
colorRedSelected = const ColorRed <$ UI.click redButton
colorBlueSelected = const ColorBlue <$ UI.click blueButton
-- we combine both the above Events to create a new one that tells us the current selected color
colorSelected = unionWith const colorRedSelected colorBlueSelected
-- accumulate values for our Behaviour, starting with ColorRed selected by default
colorMode <- accumB ColorRed modeEvent
-- create a Behaviour
mouseCoordinate <- stepper (0,0) $ UI.mousemove canvas
-- want to start with the list [1,2,3,4], but this value should change later.
-- I have 'never' here, as I don't know what else to put here yet.
listState <- accumB ([1,2,3,4]) never
-- Combine the Behaviours, we now have a tuple (chosenColorMode, mouseCoordinateTuple, savedList)
let choices = (,,) <$> colorMode <*> mouseCoordinate <*> listState
-- Apply the event (of the user clicking the canvas) to the Behaviour,
-- creating a new Event that returns the above tuple when it fires
makeChoice = choices <@ UI.click canvas
onEvent makeChoice $ \(colorMode, (x,y), savedList) -> do
...
-- in this block we use the savedList, and generate a newList.
-- I want to update the choicePosition behaviour so that the newList
-- replaces the old savedList.
完全归功于
假设我们有一个函数可以根据某些值以某种方式修改列表。 How/why updateMyList
修改列表对于这个解释并不重要,我们只需要知道它的类型。对于这个例子,我们将决定列表如何变化的值是鼠标坐标元组 (x, y),我们将其作为第一个参数传递:
updateMyList :: (Double, Double) -> [Integer] -> [Integer]
updateMyList (x, y) oldList = ...
如果我们有一个事件告诉我们用户单击时的鼠标坐标:
mouseCoords :: Behavior (Double, Double)
mouseCoords <- stepper (0,0) $ UI.mousemove canvas
mouseClicked :: Event (Double, Double)
mouseClicked = mouseCoords <@ UI.click canvas -- this is the Event we need
我们需要做的是 fmap
列表更新功能到 mouseClicked
:
listChangeEvent = fmap updateMyList mouseClicked
所以我们创建了一个新的事件:当mouseClicked
被触发时,鼠标坐标作为第一个参数传递给updateMyList
,并且这是我们在那个时间戳的新事件的价值。但这是一个部分应用的函数,updateMyList
仍然需要一个 [Integer]
作为参数,因此,listChangeEvent
具有以下类型:
listChangeEvent :: Event ([Integer] -> [Integer])
现在,这是聪明的部分:如果我们使用 accumB
并指定起始累加器(即我们的起始列表,[1,2,3,4]
),然后还使用上面的 listChangeEvent
因为事件 accumB
的值来自:
listState <- accumB ([1,2,3,4]) listChangeEvent
那么那个累加器就是将被传递给Event ([Integer] -> [Integer])
中的函数的东西。这意味着 listChangeEvent
第一次触发时,updateMyList
将被调用:
updateMyList (x, y) [1,2,3,4] -- (x, y) being the mouse coordinates at that time
并且其结果成为 listState
中的 new 累加器值,并且该新列表将用作下一个 updateMyList
的参数时间listChangeEvent
触发器,依此类推。
我们可以将它用于任何事情,它不一定是我们要修改的列表。这只是为我们提供了一种使用值初始化 Behavior 的方法,并且我们可以通过创建等同于 updateMyList
.