我发现我很少遇到需要使用where
子句的情况。但是,我确实发现我过去经常使用它。何时使用where
子句(即它使用的是什么情况)?我应该在什么情况下使用它?
答案 0 :(得分:11)
Haskell Wiki上有两个很好的答案:
http://haskell.org/haskellwiki/Declaration_vs._expression_style http://haskell.org/haskellwiki/Let_vs._Where
两者都用于创建本地定义,这些定义可能使用传递到其封闭函数范围内的值,并且当然不能在封闭函数的上下文之外使用。它们促进代码重用并最大限度地减少重复给定fix
和lambda,两者都可以完全消失。通常,我尽可能使用where子句,并且在使用前一行中通过do
提取的值时,只倾向于在lambda或case块内使用let子句,或者使用<-
表示法。总的来说,我认为声明式风格现在比惯用现代Haskell代码中的表达风格更为普遍。
答案 1 :(得分:3)
我发现它很重要的一个具体例子 - 一个返回递归定义数组的函数。
lucas :: (Integral a) => a -> Array a
lucas n = a where
a = array (0,n) ((0,2):(1,1):[(i,a!!(i-1) + a!!(i-2)) | i<-[1..n])])
对于卢卡斯数字1到n(斐波那契太明显= P)
重要的一点是,如果没有where子句,数组将不会在函数体内部具有名称,并且您无法递归定义。
答案 2 :(得分:1)
这主要是风格问题。即使它们并不完全相同,但通常不一定要使用其中一种。相反,这取决于你,你认为看起来更好。
答案 3 :(得分:0)
我的经验法则 - 如果您在函数的顶层定义某些内容,请使用“where”。如果要定义具有多个子句的辅助函数,请务必使用“where”。在其他地方,只需选择一个!
答案 4 :(得分:0)
根据我的经验,where
比let
更具可读性,因为它通常与英语类似。
例如:
myFun x = aCoefficient * (10 ** anExponent)
where aCoefficient = 100 - x
anExponent = x - 2
在英语中,我将其描述为“myFun of x是系数乘以(10到指数),其中系数是100减x,指数是x减2”
答案 5 :(得分:0)
使用where
的两个风格优势:
它将您定义的东西的值放在其名称(和类型)附近。
func x = part1 . part2 (something x)
where part1 = ...
part2 = ...
而不是
func x = let part1 =
part2 =
in part1 . part2 (something x)
它鼓励编写可以读作“报纸风格”的代码,其中重要的东西首先出现,所有细节都会在以后出现。这样,只要您觉得不需要了解其余细节,就可以停止阅读。
func x = highlevel1 . highlevel2 (x + 42)
where highlevel1 = medium (...)
highlevel2 = medium (...)
medium = ...
当绑定本身比表达式更有趣时,我主要使用let
,它们很短。例如,绑定只是为了进行模式匹配:
func x = let (MyData y _ _) = something in y
在我看来,这看起来比
更好func x = y
where (MyData y _ _) = something