我目前正在尝试创建一个类似于Haskell语法的(某种程度上)类型- am。最后,我希望取得这样的成就:
tree = group [arg1 "str", arg2 42]
[item [foo, bar] []
,item [foo, bar] []
]其中的团体和项目是同类的Node :: [Arg t] -> [Node c] -> Node t。如果这没有任何意义,那很可能是因为我不知道自己在做什么:)
我现在的问题是如何使类型系统防止我向Node提供‘错误’参数。例如,Nodes的Group类型可能只有Arg1和Arg2类型的参数,而Items可能有Foo和Bar类型的参数。
我想底线问题是:如何限制异构列表中的类型?
我试图实现的(用户)语法示例:
group .: arg1 "str" .: arg2 42
item .: foo .: bar
item .: foo .: bar其中(.:)是一个在节点中设置参数的函数。这将表示一个包含两个项的参数的组。
此外,还会有一些(伪)定义,如:
data Node = Node PossibleArguments PossibleChildNodes
type Group = Node [Arg1, Arg2] [Item]
type Item = Node [Foo, Bar] []我正在寻找一种方法,以捕获使用错误的打字机。
发布于 2013-01-17 13:04:15
根据接下来的讨论,听起来您想要创建一个DSL (特定于域的语言)来表示XML。
一种选择是将DSL嵌入到Haskell中,这样它就可以出现在Haskell源代码中。通常,您可以通过定义所需的类型并提供一组函数来处理这些类型来实现这一点。听起来这就是你想要做的。然而,作为一个嵌入式DSL,它将受到一些限制,这就是您遇到的问题。也许有一个聪明的技巧可以做你想做的事,也许是一些涉及类型函数的事情,但是我现在什么都想不出来。如果你想继续尝试,可以在你的问题中加上标签dsl和gadt,吸引比我更了解这些东西的人的注意。或者,您可以使用类似于模板Haskell或扔掉你的样板的东西来允许用户省略一些信息,这些信息会在Haskell看到“它”之前被“填入”。
另一个选项是有一个外部DSL,您可以使用Haskell解析它。您可以定义一个DSL,但也许直接用合适的DTD直接使用XML就更容易了。当然,还有用于解析XML的Haskell库。
发布于 2013-01-15 13:55:22
在我看来,你不需要一个异构的列表。也许你在找这样的东西?
data Foo = Foo Int
data Bar = Bar Int
data Arg = StringArg String | IntArg Int | DoubleArg Double
data Tree = Group Arg Arg [Item]
data Item = Item Foo Bar
example :: Tree
example = Group (StringArg "str") (IntArg 42)
[Item (Foo 1) (Bar 2), Item (Foo 12) (Bar 36)]注意,我们甚至可以创建一个不同“子类型”的Arg的列表。例如,[StringArg "hello", IntArg 3, DoubleArg 12.0]。不过,这仍将是一份同质名单。
=====编辑=====
有几种方法可以处理“默认参数”的情况。假设项目中的Bar参数是可选的。我的第一个想法是,虽然用户指定它可能是可选的,但当我存储数据时,我想要包含默认参数。这样,确定缺省值与实际使用它的代码是分开的。因此,如果用户指定的Foo为3,但没有提供Bar,默认为Bar 77,那么我将项目创建为:
Item (Foo 3) (Bar 77)这具有这样的优点,即在此对象上操作的函数不需要担心默认值;就它们而言,这两个参数都将始终存在。
但是,如果您确实希望省略数据结构中的默认参数,您可以这样做:
data Bar = Bar Int | DefaultBar
example = Group (StringArg "str") (IntArg 42)
[Item (Foo 1) (Bar 2), Item (Foo 12) DefaultBar]甚至:
data Item = Item Foo Bar | ItemWithDefaultBar Foo=====编辑#2 =====
所以也许你可以用这样的东西:
data ComplicatedItem = ComplicatedItem
{
location :: (Double, Double),
size :: Int,
rotation :: Double,
. . . and so on . . .
}
defaultComplicatedItem = ComplicatedItem { location = (0.0,0.0), size = 1, rotation = 0.0), ... }要创建ComplicatedItem,用户只需指定非默认参数:
myComplicatedItem = defaultComplicatedItem { size=3 }如果向ComplicatedItem类型添加新参数,则需要更新defaultComplicatedItem,但myComplicatedItem的定义不会更改。
您还可以重写show函数,以便它在打印时省略默认参数。
https://stackoverflow.com/questions/14338628
复制相似问题