在第7章" 来自第一原理的Haskell编程的更多功能模式"中,给出了以下数据类型:
newtype Username = Username String
newtype AccountNumber = AccountNumber Integer
data User = UnregisteredUser
| RegisteredUser Username AccountNumber
Run Code Online (Sandbox Code Playgroud)
它定义了以下功能:
printUser :: User -> IO ()
printUser UnregisteredUser = putStrLn "UnregisteredUser"
printUser (RegisteredUser (Username name)
(AccountNumber acctNum))
= putStrLn $ name ++ " " ++ show acctNum
Run Code Online (Sandbox Code Playgroud)
但是试验代码,我意识到我也可以将de printUser函数定义为:
printUser :: User -> IO ()
printUser user = case user of
UnregisteredUser -> putStrLn "UnregisteredUser"
(RegisteredUser (Username name)
(AccountNumber acctNum)) -> putStrLn $ name ++ " " ++ show acctNum
Run Code Online (Sandbox Code Playgroud)
我试图理解为什么可以使用两种这样的不同风格.它背后有一些设计动机吗?或者,有一种解释,"在这种情况下,第一种风格是首选,而在......时,最好使用第二种风格的定义"?(我的意思是,除了模糊的"可读性"动机解释之外的任何其他内容?)
对此的答案如下,强烈推荐的论文:
在4.4节中他们谈到了这个:
4.4声明风格与表达风格
随着我们讨论的发展,很明显有两种不同的风格可以编写功能程序:"声明风格"和"表达风格".[...]
声明样式尽可能尝试通过多个方程定义函数,每个方程使用模式匹配和/或保护来识别它所涵盖的案例.相反,在表达式样式中,通过将表达式组合在一起来构建更大的表达式来构建函数.[...]
我们在这里花了一些时间来确定风格选择,但是一旦我们这样做了,我们就哪种风格"更好"进行了激烈的争论.一个潜在的假设是,如果可能的话应该只有一种方式做一些事情,"所以,例如,让let和where会多余和混乱.
最后,我们放弃了潜在的假设,并为这两种风格提供了完整的语法支持.这似乎是一个典型的委员会决定,但是现在的作者认为这是一个很好的选择,我们现在认为这是一种语言的力量.
所以原因在于,当Haskell被发明时,不同的作者有不同的偏好,他们只是将这两种风格融入到语言中.所以使用你喜欢的那个.
宣言风格确实似乎更受欢迎,虽然我会说大多数人使用混合.