如何优雅地创建可选值列表?

时间:2019-04-20 14:06:07

标签: haskell

考虑以下功能

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与空列表结合使用,有没有更好的方法来创建其中可能存在或可能不存在的值列表?

3 个答案:

答案 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 ]