【问题标题】:where does the `where` clause come in handy in Haskell`where` 子句在 Haskell 中在哪里派上用场
【发布时间】:2011-08-27 07:02:21
【问题描述】:

我发现我很少遇到需要使用where 子句的情况。但是,我确实发现过去我偶尔使用过它。何时使用where 子句(即它在什么情况下使用)?什么情况下应该使用?

【问题讨论】:

  • 在适当的地方使用where
  • 您可能会在这个相关问题中找到一些有用的信息:where vs. let
  • 感谢@Thies Heidecke 甚至没有出现!

标签: haskell syntax coding-style where-clause


【解决方案1】:

Haskell Wiki 上也有这个问题的两个很好的答案:

http://haskell.org/haskellwiki/Declaration_vs._expression_style http://haskell.org/haskellwiki/Let_vs._Where

两者都用于创建本地定义,这些定义可能会使用传递到其封闭函数范围内的值,并且在封闭函数的上下文之外肯定不可用。它们促进代码重用并最大限度地减少重复。给定fix 和 lambda,两者都可以完全脱糖。通常,我尽可能使用 where 子句,并且只倾向于在 lambda 或 case 块内或在 do 表示法中使用 let 子句来定义前几行中通过 <- 提取的值。总的来说,我认为声明式风格现在比惯用的现代 Haskell 代码中的表达风格更普遍。

【讨论】:

    【解决方案2】:

    我发现它很重要的一个具体示例 - 一个返回递归定义数组的函数。

    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 子句,数组将没有函数体内的名称,并且您无法递归定义。

    【讨论】:

      【解决方案3】:

      这主要是风格问题。即使它们不完全等效,您也不会经常使用其中一个。相反,这取决于您,您认为更好看。

      【讨论】:

        【解决方案4】:

        我的经验法则 - 如果您在函数的顶层定义某些内容,请使用“where”。如果您要定义具有多个子句的辅助函数,请务必使用“where”。其他地方,随便挑一个!

        【讨论】:

        • 你的意思是在你说“where”的地方使用“let”吗?
        • 不,我经常使用“where”:)
        【解决方案5】:

        根据我的经验,wherelet 更具可读性,因为它的读法通常与英语非常相似。 例如:

        myFun x = aCoefficient * (10 ** anExponent)  
                  where aCoefficient = 100 - x  
                        anExponent = x - 2  
        

        在英语中,我将其描述为“myFun of x 是一个系数乘以(10 到一个指数),其中系数是 100 减去 x,指数是 x 减去 2”

        【讨论】:

          【解决方案6】:

          使用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
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-05-21
            • 2019-03-22
            • 2016-12-31
            • 1970-01-01
            • 1970-01-01
            • 2018-08-20
            相关资源
            最近更新 更多