Haskell:where子句引用lambda中的绑定变量



我正试图使用梯形规则对Haskell中的一个函数进行数值积分,返回一个反导数,该反导数接受要积分的区间端点的参数a、b。

integrate :: (Float -> Float) -> (Float -> Float -> Float)
integrate f
  =  a b -> d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
    where
      d = (b - a) / n
      n = 1000

在上面,我使用

n - for the number of subintervals
d - for the width of each subinterval

这几乎有效,除了lambda中的绑定参数a、b。我得到了错误消息:

Not in scope: `b'
Not in scope: `a'

我可以理解,a,b的范围仅限于lambda表达式,但是Haskell中有没有一个变通方法,这样我就不必为上面的d每次出现都写(b-a)/n了?

您认为需要返回一个函数,该函数占用两个Float并返回一个Float,但实际上这与在integrate函数中占用两个额外的Float参数并使用currying没有什么不同(即不提供它们,返回类型将为Float -> Float -> Float)。

所以你可以像这个一样重写你的函数

integrate :: (Float -> Float) -> Float -> Float -> Float
integrate f a b
  = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
    where
      d = (b - a) / n
      n = 1000

或者您可以使用let ... in而不是where:

integrate f
  = a b ->
      let d = (b - a / n)
          n = 1000
      in d * sum [ f (a + d * k) | k <- [0..n] ] - d/2.0 * (f a + f b)

当然。

integrate f a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
    where 
      d = (b - a) / n
      n = 1000

您有很多解决方案。

如果你除了lambda表达式之外不知道任何绑定语法,你可以这样做(我最喜欢它,因为它的理论美,但从不使用它,因为其语法丑陋):

integrate f
  = a b -> (d -> d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)) 
             ((b - a) / n)
    where
      n = 1000

如果你喜欢定义并且只知道where-语法,你可以这样做:

integrate f = go
  where
    n = 1000
    go a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
      where
        d = (b - a) / n

如果你也知道let-语法,你可以这样做:

integrate f = 
  a b -> let d = (b - a) / n 
          in d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
  where
    n = 1000

最后,如果你记得a -> (b -> c -> d)a -> b -> c -> d是一样的,你可以做显而易见的事情:

integrate f a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
  where
    n = 1000
    d = (b - a) / n

如果你坚持在哪里:

integrate f = a b -> case () of
    () ->  d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
           where 
               d = (b - a) / n
               n = 1000

看起来很不错,不是吗?为了让案件看起来更有动力:

integrate f = a b -> case (f a + f b) of
    fs ->  d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * fs
           where 
               d = (b - a) / n
               n = 1000

try:

integrate f a b = d * sum [ f (a + d*k) | k <- [0..n] ] - d/2.0 * (f a + f b)
    where
      d = (b - a) / n
      n = 1000

最新更新