hug*_*omg 2 haskell functional-programming data-modeling gadt
在Haskell中,它可以直接为递归树创建数据类型,就像我们使用XML文档一样:
data XML =
Text String -- Text of text node
| Elem String [XML] -- Tagname; Child nodes
Run Code Online (Sandbox Code Playgroud)
及其相关的折叠:
-- Simple fold (Child trees don't see the surrounding context.)
foldt :: (String -> a) -> (String -> [a] -> a) -> XML -> a
foldt fT fE (Text text) = fT text
foldt fT fE (Elem tagname ts) = fE tagname (map (foldt fT fE) ts)
-- Threaded fold for streaming applications.
-- See http://okmij.org/ftp/papers/XML-parsing.ps.gz
foldts :: (a -> String -> a) -> (a -> String -> a) -> (a -> a -> String -> a) -> a -> XML -> a
foldts fT fE_begin fE_end = go
where
go seed (Text text) = fT seed text
go seed (Elem tag children) =
let seed' = fE_begin seed tag in
let seed'' = foldl go seed' children in
fE_end seed seed'' tag
Run Code Online (Sandbox Code Playgroud)
我现在的问题是,我不知道如何为我的树数据类型添加一些额外的限制,以便为HTML建模.在HTML中,每个元素节点只能出现在正确的上下文中,并且每个元素对应于其子元素的不同上下文.例如:
所以我的问题是:
在Haskell98中,我需要做些什么来模拟这些限制?(我问这个是因为我猜Haskell98模型应该更好地转换为其他编程语言)
我想我们可能必须为不同的上下文创建许多不同的数据类型,但我不知道如何以原则和清晰的方式执行此操作.我怎么能这样做而不会迷路,折叠功能最终会是什么样的?
如果允许我们使用现代GHC功能(如GADT),模型会是什么样子?
我有预感GADT可能有助于将限制推进到类型检查器中,保持折叠功能简单但我对它们没有多少经验......
我不需要100%运行的解决方案,因为这显然超出了Stack Overflow讨论的范围.我只需要足够的能够更好地掌握GADT和类似的东西,并且能够自己做其余的事情.
这不需要GADT(至少还没有).您只需要向编译器传授有关树类型的更多信息.
data HTML
= HTML HTMLHeader HTMLBody
data HTMLHeader
= Header String
data HTMLBody
= Body [HTMLContent]
data HTMLContent
= Text HTMLText
| Title HTMLText
| Img String
| Elem String [HTML]
data HTMLText
= Literal String
| Bold String
| Italic String
| TextElems [HTMLText]
Run Code Online (Sandbox Code Playgroud)
现在你得到一些不变量:
-- Must have header and body. titles can't contain images.
x = HTML
(Header "TEST") $ Body [
Title (Literal "Title")
,Text (Bold "Content")
]
Run Code Online (Sandbox Code Playgroud)
派生这个树的一种有原则的方法是从特定的HTML语法中获取它 - 例如XML EBNF - http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-well-formed.
使用GADT,可以更有效地编码某些内容,并且可以在数据类型上编写可以强制执行更强不变量的函数.
当您开始使越来越多的属性可以进行静态验证时,对不变量进行编码可能会变得更加复杂.那时GADT,类型系列和其他扩展可以开始提供帮助.