如何优雅地创建可选值列表?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何优雅地创建可选值列表?相关的知识,希望对你有一定的参考价值。
考虑以下功能
annotate :: AST -> [MetaInfo]
annotate (ArgDecl name nameReq maybeVal)
= concat [
[m [Name] name],
if nameReq
then [m [Operator] "!"]]
else [],
case maybeVal of
Just v -> [annotate v]
Nothing -> []
]
...
这看起来很优雅。有没有比使用concat
和空列表更好的方法来创建可能存在或不存在的值列表?
答案
正如@AJFarmar所说,只是清理它会有所帮助:
annotate :: AST -> [MetaInfo]
annotate (ArgDecl name nameReq maybeVal)
= concat
[ [m [Name] name]
, if nameReq
then [m [Operator] "!"]
else []
, case maybeVal of
Just v -> [annotate1 v]
Nothing -> []
]
在catMaybes
的Data.Maybe
的帮助下,也可以更清楚地从singleton / empty-set切换到Just / Nothing:
annotate' :: AST -> [MetaInfo]
annotate' (ArgDecl name nameReq maybeVal)
= catMaybes
[ Just (m [Name] name)
, if nameReq
then Just (m [Operator] "!")
else Nothing
, annotate1 <$> maybeVal
]
最后,如果您更喜欢这种语法,可以考虑创建一些辅助函数并使用<>
:
annotate'' :: AST -> [MetaInfo]
annotate'' (ArgDecl name nameReq maybeVal)
= always (m [Name] name)
<> whenever nameReq (m [Operator] "!")
<> sometimes (annotate1 <$> maybeVal)
有助手:
always :: a -> [a]
always = (:[])
sometimes :: Maybe a -> [a]
sometimes = maybeToList
whenever :: Bool -> a -> [a]
whenever b a = if b then [a] else []
另一答案
当我最终得到像这样的粗略代码时,我通常会通过命名碎片来清理它:
annotate :: AST -> [MetaInfo]
annotate (ArgDecl name nameReq maybeVal)
= concat [name, bang, annotation]
where
name = [m [Name] name]
bang | nameReq = [m [Operator] "!"]]
| otherwise = []
annotation = case maybeVal of
Just v -> [annotate v]
Nothing -> []
考虑到你有一个Maybe
,我可能会去catMaybes
简化annotation
定义:
annotate :: AST -> [MetaInfo]
annotate (ArgDecl name nameReq maybeVal)
= catMaybes [name, bang, annotation]
where
name = Just $ m [Name] name
bang | nameReq = Just $ m [Operator] "!"
| otherwise = Nothing
annotation = annotate <$> maybeVal
另一答案
我倾向于将列表推广到任何Alternative
,并利用相关的函数。在这种情况下,我发现guard condition *> ...
非常好。
annotate :: Alternative f => AST -> f MetaInfo
annotate (ArgDecl name nameReq maybeVal) =
pure (m [Name] name)
<|>
guard nameReq *> pure (m [Operator] "!")
<|>
maybe empty (pure . annotate) maybeVal
或者,即使使用普通列表,使用列表推导看起来也不错。
annotate :: AST -> [MetaInfo]
annotate (ArgDecl name nameReq maybeVal) =
[m [Name] name]
++
[ m [Operator] "!" | nameReq ]
++
[ annotate v | Just v <- maybeVal ]
以上是关于如何优雅地创建可选值列表?的主要内容,如果未能解决你的问题,请参考以下文章
UIControl子类-意外地找到nil,同时隐式展开一个可选值