【问题标题】:length of list using foldr in haskell在haskell中使用foldr的列表长度
【发布时间】:2018-02-26 22:09:32
【问题描述】:

我编写了以下代码来计算列表的长度,在 haskell 中使用 foldr。当我编译代码时,它给我的错误是“myfoldr.hs:3:1: parse error on input ‘where’”。谁能告诉我这段代码中我可能遗漏了什么或做错了什么?

mylength :: [Int] -> Int
mylength l = foldr f 0 l
where
f :: Int -> Int -> Int
f x y = y+1

【问题讨论】:

  • 在 Haskell 中,空格很重要。看indentation

标签: haskell


【解决方案1】:

在 Haskell 中,空格很重要 - 查看 guide on the Haskell wiki

更正确地格式化您的代码给出:

mylength :: [Int] -> Int
mylength l = foldr f 0 l
  where
    f :: Int -> Int -> Int
    f x y = y + 1

哪个works perfectly(虽然xf 的参数有点多余,但您可能希望将其写为f _ y = y + 1,或者使用像foldr (\_ x -> x + 1) 0 l 这样的lambda 表达式。

【讨论】:

  • 非常感谢您的回答,现在它工作正常。你能解释一下为什么我们需要写 'y+1' 而不是 'x+1' 即使基值在 x 中并且我们将基值加 1 吗?
  • @SushodhanVaishampayan x 是当前的列表元素,y 是尾部的长度。所以我们想要y+1。 (请注意,在foldl 中,我们会以其他顺序查找参数——但这里我们使用的是foldr
【解决方案2】:

这是一个缩进错误:您必须缩进 where 子句,否则 Haskell 会将 f 的定义视为一个单独的函数。所以我们可以修复它:

mylength :: [Int] -> Int
mylength l = foldr f 0 l
    where f :: Int -> Int -> Int
          f x y = y+1

尽管如此,我们仍然可以使它更通用:我们可以在[a] 列表上定义它,而不是为[Int] 列表定义它,使用:

mylength :: [a] -> Int
mylength l = foldr f 0 l
    where f x y = y+1

我们也可以将f改写为const (+1),所以:

mylength :: Num n => [a] -> n
mylength = foldr (const (1+)) 0

请注意,我们可以在此处应用 eta-reduction:删除 mylength 定义的头部和主体中的 l。或者如果我们知道这个数字也是可枚举的,我们可以使用succ而不是(1+)

mylength :: (Enum n, Num n) => [a] -> n
mylength = foldr (const succ) 0

【讨论】:

  • 非常感谢您的回答,现在它工作正常。你能解释一下为什么我们需要写 'y+1' 而不是 'x+1' 即使基值在 x 中并且我们将基值加 1 吗?
  • @SushodhanVaishampayan:因为foldr的签名是(a -> b -> b) -> b -> [a] -> b,所以第二个参数就是我们更新的累加器
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多