是否可以在Haskell中对有状态节点的异构树进行编码?
在Haskell中,建模模块化静态web组件非常容易。视图是一个文档,组件只是一个返回视图的函数:是否可以在Haskell中对有状态节点的异构树进行编码?,haskell,types,functional-programming,Haskell,Types,Functional Programming,在Haskell中,建模模块化静态web组件非常容易。视图是一个文档,组件只是一个返回视图的函数: -- Renders a pretty clock clock :: Color -> Html clock color = div ... -- Renders a list of views prettily list :: [Html] -> Html list elements = div ... -- A blue clock blueClock :: Html blu
-- Renders a pretty clock
clock :: Color -> Html
clock color = div ...
-- Renders a list of views prettily
list :: [Html] -> Html
list elements = div ...
-- A blue clock
blueClock :: Html
blueClock = clock Blue
-- A list with a Blue, a Yellow, and a Red clock
clockList :: Html
clockList = list [
clock Blue,
clock Yellow,
clock Red]
这种方法的问题是当您向事物添加本地状态时。例如:
-- Added "Time" to clock's type
clock :: Color -> Time -> Html
clock color time = div ...
-- A blue clock now has a local state: its time.
blueClock :: Time -> Clock
blueClock = clock Blue
-- A list of clock must be aware of the local state of each child clock.
clockList :: [Time] -> Html
clockList times = list [
clock Blue (times !! 0),
clock Yellow (times !! 1),
clock Green (times !! 2)]
type Component state = ... ??? ...
clock :: Color -> Component Time
clock = ...
list :: [Component a] -> Component ()
list = ...
clocks :: Component ()
clocks = list [
clock Yellow (0, (+ 1)),
clock Red (0, (- 1)),
clock Blue (0, (+ 2))]
runComponent :: Component a -> IO HtmlNode
父节点必须知道每个子节点的本地状态,这打破了模块化。我们需要一种编码自包含组件的方法,而不是单纯的视图,每个组件将定义如何处理自己的内部状态。例如:
-- Added "Time" to clock's type
clock :: Color -> Time -> Html
clock color time = div ...
-- A blue clock now has a local state: its time.
blueClock :: Time -> Clock
blueClock = clock Blue
-- A list of clock must be aware of the local state of each child clock.
clockList :: [Time] -> Html
clockList times = list [
clock Blue (times !! 0),
clock Yellow (times !! 1),
clock Green (times !! 2)]
type Component state = ... ??? ...
clock :: Color -> Component Time
clock = ...
list :: [Component a] -> Component ()
list = ...
clocks :: Component ()
clocks = list [
clock Yellow (0, (+ 1)),
clock Red (0, (- 1)),
clock Blue (0, (+ 2))]
runComponent :: Component a -> IO HtmlNode
请注意:
state->state
,它被称为每个“勾号”来更新其本地状态。有些钟倒着走,有些钟以双倍的速度走列表
是没有本地状态的组件。它只是创建了一些包含许多组件的漂亮HTML列表。它根本不知道内部时钟的局部状态runComponent
负责赋予最终应用程序生命,包括正确调用每个子组件的状态我尝试了无数种用类型形式化这种直觉的方法,但我找不到任何令人满意的方法。问题包括组件可以具有不同类型的状态,以及“回调”(例如,纯按钮)必须影响包含它的组件的状态。如何在Haskell的类型系统中对此类系统进行编码?尝试存在类型。您描述的问题听起来与Snaplet在snap server框架中解决的问题非常相似;它基本上使用镜头以自己的状态运行Snaplet。你可以考虑阅读SNAPLET是如何工作的,看看它们的方法是否适合你。我正在寻找这样的建议,谢谢指针!我不清楚你在问什么。如果列表中的数据取决于当前时间,那么列表的值当然也取决于时间。在纯函数设置中,无法“隐藏”这种依赖关系。您可以通过将某个对象的内部状态设置为函数的参数,并将该状态向下传递,来“隐藏”该对象的内部状态。例如,
listOfWords=(“lih”、\x->div[(“foo”、\x->div(strx))、(“bar”、\x->div(str(x+x))、(“biz”、\x->div(str(x*3))))
。这里,每个组件都有一个id(“foo”、“bar”…)和一个内部状态x
listOfWords
不知道其子项的状态。函数runComponent
将传递状态环境,以便每个节点根据其id接收自己的状态。这将隐藏在允许模块化的意义上,@BenjaminHodgson。