我有一个代表命令行选项的数据类型:
data Flag = Verbose | Help | Buffer Int deriving (Show, Eq)
当程序运行时,我会得到一个
Flag
列表,对应于用户指定的选项。例如,[Buffer 10, Verbose]
。
我的问题是,从
Int
中的 Buffer
中提取 [Flag]
值的最佳方法是什么?Buffer
。case
语句从其他 Buffer
中过滤掉 Flag
。
作为起点,考虑这个函数:
buffers :: [Flag] -> [Int]
buffers xs = [b | Buffer b <- xs]
它返回
Int
内部的 Buffer
的列表。对于[Verbose, Help]
,它将返回[]
。对于[Buffer 10, Verbose]
,它将返回[10]
。对于[Buffer 123, Buffer 456]
,它将返回[123, 456]
。
现在你有一个
[Flag] -> [Int]
。如果您还想出了一个 [Int] -> Int
,您可以组合它们以获得您最初要求的 [Flag] -> Int
,所以现在取决于您如何从该列表中获取单个整数。
listToMaybe
是一种方法。如果列表为空,它将返回 Nothing
,否则返回 Just
第一个元素。如果未提供,请与 fromMaybe
组合以设置默认缓冲区大小。
或者,您可以以某种方式组合多个缓冲区参数。
maximum (0:buffers xs)
将返回指定的最大缓冲区大小,如果没有则返回 0。 (如果没有 0:
,如果没有指定缓冲区大小,程序将会崩溃。)sum (buffers xs)
将返回所有指定缓冲区大小的总和(如果没有指定缓冲区大小,则自动返回 0,因为空总和为 0 ).
对此有一个非常简单的解决方案。
首先,实现一个类型来表示程序行为的完整描述:
data Mode = NormalMode { verbose :: Bool, buffer :: Int } | HelpMode
然后,实现一个更新函数来根据 one 标志和默认参数数组更新参数:
defaults :: Mode
defaults = NormalMode { verbose = False, buffer = defaultBuffer }
-- assuming defaultBuffer is defined somewhere
update :: Flag -> Mode -> Mode
update Help _ = HelpMode
update _ HelpMode = HelpMode
update Verbose NormalMode { buffer = b } = NormalMode { verbose = True, buffer = b }
update (Buffer n) NormalMode { verbose = v } = NormalMode { verbose = v, buffer = n }
然后,要解析
Flag
列表,只需使用 foldr
或 foldl
:
parseFlagsR :: [Flag] -> Mode
parseFlagsR = foldr update defaults
-- This prioritizes the leftmost Buffer flag
parseFlagsL :: [Flag] -> Mode
parseFlagsL = foldl (flip update) defaults
-- This prioritizes the rightmost Buffer flag
然后,您可以通过以下任何一种方式获取缓冲区,但我推荐最后一种:
safeGetBuffer :: Mode -> Maybe Int
safeGetBuffer NormalMode { buffer = b } = Just b
safeGetBuffer _ = Nothing
getBufferWith :: Int -> Mode -> Int
getBufferWith _ NormalMode { buffer = b } = b
getBufferWith n _ = n
getBuffer :: Mode -> Int
getBuffer = getBufferWith defaultBuffer
-- defaultBuffer from earlier, again, assuming it's defined.
这个解决方案比 Joseph Sible 的答案更通用,并且在提取详细值时可能很有用。这也明确地制定了标志的优先级,并方便地将所有更新操作捆绑在一起。
此外,如果您想了解更多有关其一般实现的信息,我建议您熟悉镜头和其他光学器件。