我想格式化这个功能:
getEnv :: [Func] -> ([Char] -> RetType)
getEnv [] = (\_ -> undefined)
getEnv ((Func (RetTypeType t) (Ident fname) _ _):fs) = (\x -> if x == fname then t else getEnv fs)
问题是由长模式匹配引起的,现在我不想更改构造函数的名称。第三行中函数的右侧部分也不容易为我格式化。
虽然不管是生死攸关的问题,但我很好奇你如何格式化这段代码。感谢。
答案 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)
首先,我尝试保持模式简单。通常它只是一个带变量或下划线的构造函数作为它的参数。例外:像(:)或(,)这样的内置构造函数不计算在内。所以,如果你有那种模式匹配,我认为你做错了。
其次,我只是将这一行拆分为'='而感到高兴。