格式化长模式匹配

时间:2014-01-16 11:24:12

标签: haskell code-formatting

我想格式化这个功能:

getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)
getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) = (\x -> if x == fname then t else getEnv fs)

问题是由长模式匹配引起的,现在我不想更改构造函数的名称。第三行中函数的右侧部分也不容易为我格式化。

虽然不管是生死攸关的问题,但我很好奇你如何格式化这段代码。感谢。

3 个答案:

答案 0 :(得分:6)

基本上,您有两种可能性:

这样的事情:

getEnv ((Func 
          (RetTypeType t) 
          (Ident fname) _ _)
       :fs) 
    = (\x -> if x == fname then t else getEnv fs)

或者您可以使用图案防护:

getEnv (h:fs)
  | Func a b _ _ <- h,
    Rectype t <- a,
    Ident fname <- b 
  = (\x -> if x == fname then t else getEnv fs)

你可以进一步避免lambda:

getEnv (h:fs) x
  | Func a b _ _ <- h,
    Rectype t <- a,
    Ident fname <- b 
  = if x == fname then t else getEnv fs

“开放”模式保护的缺点可能是编译器无法再决定您的模式是否详尽无遗。

正如@leftaroundabout指出的那样,我们可以更清楚地说明这一点:

getEnv (h:fs) x
  | Func a b _ _ <- h,
    Rectype t <- a,
    Ident fname <- b,
    x == fname         = t
  | otherwise          = getEnv fs

这也可以让编译器知道列表头部的所有可能形式都被覆盖了,所以我称之为最优选的方式。

答案 1 :(得分:2)

我通常只是做

getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)

getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) 
          = \x -> if x == fname then t else getEnv fs

但是,如果我做了很多使用记录语法的话,我会倾向于

data Func = Func {returnTypeType :: RetTypeType,
                  identifier :: Ident,
                  .... }
data RetTypeType = RetTypeType {unRetTypeType :: RetType}
data Ident = Ident {unIdent:: String}

所以我可以写

getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)
getEnv (f:fs) = \x -> if x == ident f 
                      then unRetTypeType.returnTypeType $ f 
                       else getEnv fs

答案 2 :(得分:0)

首先,我尝试保持模式简单。通常它只是一个带变量或下划线的构造函数作为它的参数。例外:像(:)或(,)这样的内置构造函数不计算在内。所以,如果你有那种模式匹配,我认为你做错了。

其次,我只是将这一行拆分为'='而感到高兴。