Haskell中用于MVC框架的镜头

7
我一直在考虑如何像WPF或AngularJS那样在Haskell中构建一个MVC框架,但似乎找不到开始的关键类型或思路。因此,很遗憾,我的问题很笼统:还有其他人在考虑这个问题吗?
我看到了edit-lenses、multi-plate和Compos,但我认为它们都解决了稍微不同的问题。
我对如何实现的初步想法是:
1.创建一个模型作为纯Haskell数据结构
2.创建一组“镜头”或命令来修改模型。
3.编写一个HTML(或任何其他)模板,该模板参数化了模型中的类型。
data Model = Page { _title :: String, _content :: [(Int, String)] }

title :: Lens Model String
content :: Int -> Lens Model (Maybe String)

然后我希望能够编写一个函数:
Model -> Template Model -> Html

我需要一个函数,在应用镜头时能够更新视图的部分内容。

Lens Model a -> a -> HtmlTemplate Model -> [(Path, Html)]

我想问题是:如果一个镜头可以在一个数据结构上运行,然后用于描述另一个数据结构的变化,它需要采取哪种类型。

一种可能性似乎是创建一个包装所有镜头的GADT,然后在GADT类型上模板化HTML,然后可以在每个步骤上匹配模板。例如:

data Lenses a b where
    Title :: Lens Model String -> Lenses Model String
    Item  :: Lens Model String -> Lenses Model (Maybe String)

然后是一个 HTML 模板数据类型,例如:
data HtmlTemplate a = Text String 
              | Element String [Attrib a] 
              | forall b. Binding (Lenses a b) (Html b)

可以直接与绑定元素进行模式匹配。

但这似乎几乎是在打击要点,因为模型随后与视图紧密结合。

我想知道有没有任何比我更聪明的人考虑过这可能如何工作?或者这是否是个好主意?


1
我开始了一个实验性的镜头库,旨在支持任意有副作用的操作,你可能会对它感兴趣(目前不能推荐你使用它,因为API将会改变,它是实验性的,并且当它在Reddit上被讨论时遭到了猛烈的批评)。与你的情况最接近的是this post中的最后一个例子;当你在模型上进行镜头操作时,你可能希望在State中修改你的视图:LensM (State View) Model a或类似的东西。但我没有经常使用MVC模式,所以如果我说错了,请原谅。 - jberryman
我认为这至少是解决方案的一半,因此您可以构建更改以查看(或直接修改视图)。但是,我认为我缺少的是一种遍历模型和视图(模板化模型)的机制 - 一种同时遍历两个相关结构的压缩机制。 - Oliver
你可能会对http://www.haskellforall.com/2014/04/model-view-controller-haskell-style.html感兴趣。 - hdgarrood
1个回答

9

我一直在使用基于镜头的“MVC”来构建一个大型商业应用程序,使用Haskell编写。

  • 纯函数数据结构
  • 镜头用于设置和获取(并保持数据一致性)
  • 用于生成与每个镜头相关联的视图(模板)的DSL。

这是一个很好的体验,我绝对推荐这种方法用于复杂结构的详细结构编辑。

这种方法迫使您

  • 不要进行黑客攻击,而是使用镜头作为安全接口来访问内部模型
  • 强制将模型与视图分离
  • 对所有内容进行类型检查 - 镜头类型用于生成视图代码

有很多设计方式,但我认为这是一种非常合理的设计方法。您需要良好的GUI部分DSL支持。


2
你能详细说明一下"A DSL for generating a view (template) tied to each lens."是什么吗?听起来非常酷。 - jberryman
1
基本上,这是一种模板语言,它将屏幕上的类型控件与其对应的镜头关联起来。因此,按钮、文本输入、数字输入等可以链接到该输入的编辑镜头,并且这些镜头的图形可以被连接起来。然后,用户界面就会自动生成。 - Don Stewart
听起来不错。我想使用类似的方法使用Html作为UI来制作本地Web应用程序(或者有一天使用UHC Javascript)。干杯 :) - Oliver
@Oliver听起来很像表单组件。 - Mauricio Scheffer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接