考虑以下功能
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
与空列表结合使用,有没有更好的方法来创建其中可能存在或可能不存在的值列表?
答案 0 :(得分:3)
正如@AJFarmar指出的那样,只需清理它会有所帮助:
async
在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 -> []
]
的{{1}}的帮助下,更容易从单例/空集切换为正/无:
catMaybes
最后,如果您喜欢以下语法,则可以考虑创建一些辅助函数并使用Data.Maybe
:
annotate' :: AST -> [MetaInfo]
annotate' (ArgDecl name nameReq maybeVal)
= catMaybes
[ Just (m [Name] name)
, if nameReq
then Just (m [Operator] "!")
else Nothing
, annotate1 <$> maybeVal
]
有助手:
<>
答案 1 :(得分:3)
当我得到像这样的代码时,我通常通过命名代码来清理它:
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
答案 2 :(得分:3)
我倾向于将列表推广到任何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 ]