1

注意:这与互斥的并发问题无关,但我想不出更好的方式来描述这个问题。

我有一个问题,我想让用户选择一些标志,但有些标志是互斥的。我想使用数据结构来描述哪些标志是互斥的,但我所想到的一切都很笨拙。

基本上,我希望能够指定如何使用标志,如下所示:

[-fa | -e | -d ] [ -c ] [ -g | -H ]

这在语义上应该意味着,我可以有 -fa、-e、-d 中的任何一个,但不能有两个或更多(但是,f 可以与 a 一起使用,您不需要同时使用两者)。我可以有或没有-c,我可以有-g或-h,但不能同时有。

这是我的“最佳”解决方案。

Map[Flag, MutexGroup] (及其逆, Map[MutexGroup, List[Flag]]) Map[MutexGroup, List[MutexGroup]]

我的例子会是什么样子

映射(“f”-> 1、“a”-> 1、“e”-> 2、“d”-> 3、“c”-> 4、“g”-> 5、“h”-> 6 ) Map(1 -> List(2, 3), 2 -> List(1, 3), 3 -> List(1, 2), 4 -> List.empty, 5 -> List(6), 6 - > 列表(5))

为简洁起见,我没有包含 Map[MutexGroup, List[Flag]]。

这个解决方案让我一想到必须使用它就感到不寒而栗。有处理这种事情的规范方法吗?

4

1 回答 1

3

您正在描述一种语法。

表示语法的最佳方式是抽象语法树。树是代表(互斥)选择的规范结构。

您可以通过多种方式表示语法树,但一种很好的方法是使用代数数据类型,因为它们静态地保证只能构造格式良好的表达式。标志本身形成一个集合,因此使用Set数据类型来强制执行 no-duplicates 属性也很好。

-- can have any one of -fa, -e, -d, but not two or more
-- (however, f can be used with a, and you don't need to use both).
-- I can either have a -c or not, and I can have either -g or -h, but not both.
--

-- zero or more flags
type Flags = Set Flag

-- Flags come in three groups
data Flag
        = F1 FAED
        | F2 C
        | F3 GH
    -- equality up to the first constructor. 

-- one of: -f or -a; -e; -d
data FAED
        = FA FA 
        | E
        | D

-- a type for: -f ; -a ; -f -a
data FA = F
        | A
        | FA

-- the -c flag
data C  = C

-- either -g or -h
data GH = G
        | H

还有其他方法可以对您的语言进行编码,但这足以让您开始使用语法树表示语言的路径。

于 2012-06-04T13:44:10.197 回答