注意:这与互斥的并发问题无关,但我想不出更好的描述问题的方法。
我有一个问题,我有一个案例,我想让用户选择一些标志,但一些标志是互斥的。我想用数据结构描述哪些标志是互斥的,但我想到的一切都很笨拙。
基本上,我希望能够指定如何使用标志:
[-fa | -e | -d] [-c] [-g | -h]
这应该在语义上意味着,我可以使用-fa,-e,-d中的任何一个,但不能有两个或更多(但是,f可以与a一起使用,而且不需要同时使用它们)。我可以有一个-c或者没有-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) 地图(1 - >列表(2,3),2 - >列表(1,3),3 - >列表(1,2),4 - > List.empty,5 - >列表(6 ),6 - >列表(5))
为简洁起见,我没有包含Map [MutexGroup,List [Flag]]。
这个解决方案让我不禁想到必须要使用它。是否有规范的方法来处理这类事情?
答案 0 :(得分:2)
你正在描述一种语法。
表示语法的最好方法是抽象语法树。树是规范结构,代表(互斥)选择。
您可以通过多种方式表示语法树,但一种不错的方法是使用algebraic data types,因为它们静态地保证只能构造格式良好的表达式。标志本身形成一个集合,因此使用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
还有其他方法可以对您的语言进行编码,但这足以让您沿着使用语法树表示语言的道路前进。