是否有可能在Haskell中对有状态节点的异构树进行编码?

时间:2015-12-01 23:01:02

标签: 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
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

请注意:

  1. Clock是具有Time类型的本地状态的组件。实例需要一个初始状态(此处始终为0)和一个函数state -> state,它被称为每个“tick”以更新其本地状态。有些时钟倒退,有些时钟以双倍速度运行......

  2. list是没有本地状态的组件。它只是创建了一些包含许多组件的漂亮HTML列表。它根本不知道内部时钟的本地状态。

  3. runComponent负责赋予最终应用程序生命,包括正确调用每个子组件的状态。

  4. 我已尝试过无数种方式将这种直觉与类型形式化,但我找不到任何令人满意的东西。问题包括组件可以具有不同类型的状态,以及“回调”(例如,在纯按钮上)必须影响包含它的组件的状态这一事实。如何在Haskell的类型系统中编码这样的系统?

0 个答案:

没有答案