【问题标题】:Haskell: Parse Error in nested where clauseHaskell:嵌套where子句中的解析错误
【发布时间】:2016-08-21 09:27:26
【问题描述】:

我有以下代码,它实现了筛子或 Eratosthenes:

primeSieve :: Int -> [Int] -- Returns a list of primes up to upperbound
primeSieve upperbound = filter[2..upperbound] 
  where filter ls indx = 
    let divisor = (ls!!indx)
    let filtered = [x | x <- ls, x `mod` divisor /= 0]
    if divisor*divisor >= last filtered
      then filtered
      else filter filtered (indx+1)

我在第 4 行收到一个解析错误,“可能不正确的缩进或不匹配的括号”。

这是为什么?

【问题讨论】:

    标签: haskell


    【解决方案1】:

    我相信你想用 do-notation 写filter。您可以在filter ls indx = 之后添加do。但是,这段代码是纯粹的(即非单子的),我会推荐这种语法:

    primeSieve :: Int -> [Int] -- Returns a list of primes up to upperbound
    primeSieve upperbound = filter [2..upperbound]
      where
        filter ls indx =
            let divisor = (ls!!indx)
                filtered = [x | x <- ls, x `mod` divisor /= 0]
            in if divisor*divisor >= last filtered
              then filtered
              else filter filtered (indx+1)
    

    ...但是您的代码给了我以下错误:

    <file>:13:25:
    Couldn't match expected type `[Int]'
                with actual type `Int -> [Int]'
    Probable cause: `filter' is applied to too few arguments
    In the expression: filter [2 .. upperbound]
    In an equation for `primeSieve':
        primeSieve upperbound
          = filter [2 .. upperbound]
          where
              filter ls indx
                = let ...
                  in
                    if divisor * divisor >= last filtered then
                        filtered
                    else
                        filter filtered (indx + 1)
    Failed, modules loaded: none.
    

    我认为您的意思是将0 作为第二个参数传递给filter

    primeSieve :: Int -> [Int] -- Returns a list of primes up to upperbound
    primeSieve upperbound = filter [2..upperbound]
      where
        filter ls indx =
            let divisor = (ls!!indx)
                filtered = [x | x <- ls, x `mod` divisor /= 0]
            in if divisor*divisor >= last filtered
              then filtered
              else filter filtered (indx+1)
    

    【讨论】:

    • “in if”是什么意思?
    • 这只是一个let ... in 子句,后跟一个if 表达式。这里没有什么神奇的。
    【解决方案2】:

    问题是filter 定义的缩进比它应该的要小。重要的部分是

    where filter ls indx = 
      let divisor = (ls!!indx)
    

    let 在上面一行的 filter 之前的 4 个字符处开始。这会触发语法错误。要修复它,您可以缩进更多 filter 定义

    where filter ls indx = 
            let divisor = (ls!!indx)
    

    更常见的格式是

    where
      filter ls indx = 
        let divisor = (ls!!indx)
    

    因为这样你不会缩进太多。

    您可以在haskell wiki 上找到有关缩进的更多信息,其中包含有关此类错误的一些很好的视觉示例。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2023-04-02
      • 2016-12-31
      • 1970-01-01
      • 2021-07-05
      • 2017-08-16
      • 2019-03-22
      • 1970-01-01
      相关资源
      最近更新 更多