在 Haskell 中使用嵌套的“where”子句
Using nested `where` clauses in Haskell
在学习 Haskell 的过程中,我必须对 return 给定数字的所有整数除数执行一个函数。所以,我使用两个嵌套的 where
子句创建了它,但它不起作用。
错误 return编辑:exs2.hs:49:24: Parse error in pattern: negRef / 2
divisors' :: (Integral a) => a -> [a]
divisors' x = divs x (x/2) [x]
where
divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list)
divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list
where
negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList)
negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList
那有什么不对的呢?好像缩进得很好。
您的第二个 where
子句未使用 divs
范围内的任何名称。您可以像这样只使用一个子句:
divisors' :: (Integral a) => a -> [a]
divisors' x = divs x (x/2) [x]
where
divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list)
divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list
negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList)
negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList
如果你真的想用嵌套子句来表达你的功能,你可以使用let ... in
。
但在这种情况下这没有用,我建议使用 where
子句(它通常优于 let ... in
,在大多数情况下被认为不太惯用)。
它不起作用的原因是该子句附加到 divs
的第二个等式,而不是第一个使用 negDiv
.
的等式
PS:由于 ,negRef/2
不是有效模式,这就是您的错误来源。
另一个问题是 /
运算符不适用于整数。在 Haskell 中,/
是字段的除法运算符,因此需要 Fractional
类型,例如 Rational
或 Double
.
对于 整数 除法你应该使用 div
or quot
.
你有几个问题:
- 您只能对文字和数据构造函数进行模式匹配,不能像
/
. 这样的任意函数
/
仅为 Fractional a
值定义,而不是 Integral
。请改用 div
。
- 您对
negDiv
的定义在递归调用中缺少参数。不过,尚不清楚参数应该是什么。
大部分更正的版本:
divisors' :: (Integral a) => a -> [a]
divisors' x = divs x (x `div` 2) [x]
where
divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list)
divs ref num list | ref `mod` num == 0 = divs ref (num-1) (num:list)
| otherwise = divs ref (num-1) list
-- Three arguments, but only two given to each recursive call
negDiv x y negList | x == negRef `div` 2 = x:y:negList
| x `mod` y == 0 = negDiv (y-1) (y:negList)
| otherwise = negDiv (y-1) negList
顺便说一下,使用
可以更简单地完成此操作
divisors' x = ds ++ (map negate ds) -- positive and negative ds
where ds = filter (divs x) [1..x] -- d such that d divides x
x `divs` y = x `mod` y == 0 -- Does y divide x?
甚至
divisors' x = [d | d <- [(-x)..x], d /= 0, x `mod` d == 0]
每当您发现自己编写递归函数来遍历列表时,您可能会忽略正确的高阶函数或列表理解。
在学习 Haskell 的过程中,我必须对 return 给定数字的所有整数除数执行一个函数。所以,我使用两个嵌套的 where
子句创建了它,但它不起作用。
错误 return编辑:exs2.hs:49:24: Parse error in pattern: negRef / 2
divisors' :: (Integral a) => a -> [a]
divisors' x = divs x (x/2) [x]
where
divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list)
divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list
where
negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList)
negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList
那有什么不对的呢?好像缩进得很好。
您的第二个 where
子句未使用 divs
范围内的任何名称。您可以像这样只使用一个子句:
divisors' :: (Integral a) => a -> [a]
divisors' x = divs x (x/2) [x]
where
divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list)
divs ref num list = if (mod ref num == 0) then divs ref (num-1) (num:list) else divs ref (num-1) list
negDiv negRef (negRef/2) negList = (negRef:(negRef/2):negList)
negDiv negRef negNum negList = if (mod negRef negNum == 0) then negDiv (negNum-1) (negNum:negList) else negDiv (negNum-1) negList
如果你真的想用嵌套子句来表达你的功能,你可以使用let ... in
。
但在这种情况下这没有用,我建议使用 where
子句(它通常优于 let ... in
,在大多数情况下被认为不太惯用)。
它不起作用的原因是该子句附加到 divs
的第二个等式,而不是第一个使用 negDiv
.
PS:由于 negRef/2
不是有效模式,这就是您的错误来源。
另一个问题是 /
运算符不适用于整数。在 Haskell 中,/
是字段的除法运算符,因此需要 Fractional
类型,例如 Rational
或 Double
.
对于 整数 除法你应该使用 div
or quot
.
你有几个问题:
- 您只能对文字和数据构造函数进行模式匹配,不能像
/
. 这样的任意函数
/
仅为Fractional a
值定义,而不是Integral
。请改用div
。- 您对
negDiv
的定义在递归调用中缺少参数。不过,尚不清楚参数应该是什么。
大部分更正的版本:
divisors' :: (Integral a) => a -> [a]
divisors' x = divs x (x `div` 2) [x]
where
divs ref 1 list = negDiv (-ref) (-2) ((-1):1:list)
divs ref num list | ref `mod` num == 0 = divs ref (num-1) (num:list)
| otherwise = divs ref (num-1) list
-- Three arguments, but only two given to each recursive call
negDiv x y negList | x == negRef `div` 2 = x:y:negList
| x `mod` y == 0 = negDiv (y-1) (y:negList)
| otherwise = negDiv (y-1) negList
顺便说一下,使用
可以更简单地完成此操作divisors' x = ds ++ (map negate ds) -- positive and negative ds
where ds = filter (divs x) [1..x] -- d such that d divides x
x `divs` y = x `mod` y == 0 -- Does y divide x?
甚至
divisors' x = [d | d <- [(-x)..x], d /= 0, x `mod` d == 0]
每当您发现自己编写递归函数来遍历列表时,您可能会忽略正确的高阶函数或列表理解。