2014-01-16 40 views
2

我想格式化这个功能:格式化长模式匹配

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

问题是由长模式匹配造成的,现在我不想改变构造函数的名称。另外第三行功能的右侧部分对我来说也不容易格式化。

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

回答

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) 

你可以进一步避免拉姆达:

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 

这也将让编译器知道该列表的头部的所有可能的形式都包括在内,所以这个我” d术语是实现它的最佳方式。

+0

当你已经在模式守卫,为什么不在那里包括'x == fname'条件?它非常适合。 - 另一方面,我更喜欢把逗号放在一开始,与'|'一致,就像Haskell中相当常见的样式一样(当然,这是一个有趣的事情)。 – leftaroundabout

+0

@leftaroundabout看到,当行以逗号开始时,我可能会讨厌它。除此之外。我将编辑我的帖子以显示'x == fname' – Ingo

+0

Exaustive答案,我选择最后的样式,谢谢! – optimusfrenk

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 
0

首先,我尝试保持模式si mple。通常它只是一个带变量或下划线的构造函数,因为它是参数。异常:像(:)或(,)这样的内置构造函数不计数。所以,如果你有这种模式匹配,我认为你做错了什么。其次,我只是将'='分开并且很高兴。