4

定义 Haskell 函数的经典方法是

f1 :: String -> Int
f1 ('-' : cs) -> f1 cs + 1
f1 _ = 0

我对在每一行都写函数名有点不满意。现在我通常以以下方式编写,使用模式保护扩展,并认为它更具可读性和修改友好性:

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

您认为第二个示例更具可读性、可修改性和优雅性吗?生成的代码呢?(还没有时间查看脱糖输出,抱歉!)。什么是缺点?我唯一看到的是扩展用法。

4

2 回答 2

8

好吧,你总是可以这样写:

f3 :: String -> Int
f3 s = case s of
           ('-' : cs) -> f3 cs + 1
           _          -> 0

这与版本的含义相同f1。如果该函数有一个冗长或难以阅读的名称,并且您想匹配很多模式,这可能是一个改进。对于您的示例,我将使用常规语法。

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

于 2012-09-13T13:55:04.827 回答
6

当我对某些东西进行模式匹配时,我更喜欢编写函数名称,如您的案例所示。我觉得它更具可读性。

当我对函数参数有一些条件时,我更喜欢使用守卫,这有助于避免if else,如果我要遵循第一个模式,我将不得不使用它。

所以回答你的问题

Do you think that second example is more readable, modifiable and elegant?

不,我更喜欢第一个简单易读的。但或多或少取决于你的个人品味。

What about generated code?

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

What are cons? 

好吧,patternguards 对模式匹配很有用,而不是使用 let 或更干净的东西。

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

好吧,当然你需要使用扩展名,而且它不是 Haskell98(你可能不会认为这是一个缺点)

另一方面,对于函数参数的简单模式匹配,我将只使用第一种方法,它简单易读。

于 2012-09-13T13:58:55.097 回答