Haskell 带保护的函数定义

Haskell 带保护的函数定义,haskell,Haskell,定义Haskell函数的经典方法是 f1 :: String -> Int f1 ('-' : cs) -> f1 cs + 1 f1 _ = 0 我有点不满意在每一行写函数名。现在我通常用下面的方式写,使用模式保护扩展,并认为它更可读和修改友好: f2 :: String -> Int f2 s | '-' : cs <- s = f2 cs + 1 | otherwise = 0 f2::String->Int f2 s |“-”:cs你可以这样写: f3

定义Haskell函数的经典方法是

f1 :: String -> Int
f1 ('-' : cs) -> f1 cs + 1
f1 _ = 0
我有点不满意在每一行写函数名。现在我通常用下面的方式写,使用模式保护扩展,并认为它更可读和修改友好:

f2 :: String -> Int
f2 s
  | '-' : cs <- s = f2 cs + 1
  | otherwise = 0
f2::String->Int
f2 s

|“-”:cs你可以这样写:

f3 :: String -> Int
f3 s = case s of
           ('-' : cs) -> f3 cs + 1
           _          -> 0
这与
f1
版本的含义相同。如果函数的名称很长或很难读懂,并且您希望匹配许多模式,那么这可能是一种改进。对于这里的示例,我将使用常规语法


您的
f2
版本本身没有什么问题,但似乎对语法GHC扩展的使用有点轻率,这还不足以假设每个人都熟悉它。对于个人代码来说,这没什么大不了的,但是我会坚持使用
case
表达式来表示您希望其他人阅读的任何内容。

我更喜欢在模式匹配时编写函数名,如您的案例所示。我觉得它更可读

当我对函数参数有一些条件时,我更喜欢使用卫士,这有助于避免
if else
,如果我要遵循第一种模式,就必须使用卫士

来回答你的问题

Do you think that second example is more readable, modifiable and elegant?
不,我喜欢第一个简单易读的。但这或多或少取决于你的个人品味

What about generated code?
我认为生成的代码不会有任何区别。两者都只是模式匹配

What are cons? 
patternguards对于patternmatch很有用,而不是更干净地使用let或其他东西

addLookup env var1 var2
   | Just val1 <- lookup env var1
   , Just val2 <- lookup env var2
   = val1 + val2
addLookup env var1 var2

|只需在
f2
中使用val1,您将不得不重复
,因此我将使用旧的案例:)It案例一个缺点:它无法在多个参数上匹配:
f0=[];f[]=[];fn(x:xs)=f(n-1)xs