我有以下代码:
betaRest :: Int -> [Int] -> Int
betaRest n prevDigits | n == 0 = (length prevDigits)
| otherwise = (sum (map (betaRest (n - 1)) [0..9]))
betaFirst :: Int -> Int
betaFirst n | n == 0 = 0
| otherwise = (betaRest (n - 1) [1..9])
它给了我以下错误,我不知道为什么 .
1)算术序列'0 .. 9'中没有(Enum [Int])的实例2)没有来自文字'0'的(Num [Int])实例
Haskell是否认为使用“..”运算符创建的内容是枚举?但是为什么下面的4行(“[1..9]”)的行不存在错误呢?
编辑:我想要的代码是这样的(程序性的):
int betaRest(int n, int[] prevDigits) {
if (n == 0) return prevDigits.length;
else {
sum = 0;
foreach prevDigit in prevDigits {
sum += betaRest(n - 1, [0..9]);
}
return sum;
}
}
int betaFirst(int n) {
if (n == 0) return 0;
else return betaRest(n - 1, [1..9]);
}
因此,betaFirst(1)== 9,betaFirst(2)== 90.是的,有人可能想建议生成这个的公式,但我要添加某种过滤器[0..9 ],从而缩小范围 .
2 回答
您将
betaRest
传递给map
. Map 是(a -> a) -> [a] -> [a]
所以对于[Int]
列表你传递它想要一个Int -> Int
函数 . 但部分应用betaRest
是[Int] -> Int
.至于
[0..9]
,它的类型是(Enum t, Num t) => [t]
,它被翻译成enumFromTo 0 9
应用程序 . 所以编译器反过来想出你的错误:如果为列表定义特殊的Num
和Enum
实例,那么[0..9]
就会成为int列表的列表,那么你的应用程序就有意义了 .但我认为你想使用
inits
或tails
函数 . 让我们知道您想要实现的目标,以便我们可以提供解决方案 .最小的修复方法是将
prevDigits
作为参数添加到map
并使用lambda抽象来忽略未使用的prevDigit
:让我们减少括号的数量,以便更好地了解会发生什么 .
sum
的论点是现在,
betaRest :: Int -> [Int] -> Int
,因此部分应用函数的类型是因此我们可以推断出类型
但传递给
map (betaRest (n-1))
的参数是[0 .. 9]
,它有类型Num
约束来自使用整数文字,而Enum
约束来自enumFromTo
函数的使用(以其语法 - 加糖形式[low .. high]
) . 将其作为参数传递给期望类型为[[Int]]
的参数的函数意味着必须将类型变量a
实例化为[Int]
,然后需要检查约束,即必须查找[Int]
的实例Num
和Enum
. 这些都不存在,因此出现错误消息 .我不确定你的程序示例是否真的是你想要的,
foreach
循环更容易(也更有效)表达为所以对于
foreach
来说,循环体中应该依赖prevDigit
.对Haskell的翻译将是
但如上所述,我怀疑这真的是你想要的 .