哈斯克尔错误:\“没有实例(枚举[INT])(Haskell Error: \"No instanc

2019-09-23 07:35发布

我有以下代码:

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)任何实例(枚举[INT])从算术序列所产生的 '0 .. 9'

2)没有实例从字面产生(民[INT])“0”

难道哈斯克尔认为,与“..”运营商做的事情是枚举? 但是,为什么是不是有,下面是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 ],从而降低的范围内。

Answer 1:

您传递betaRestmap 。 地图是(a -> a) -> [a] -> [a]所以[Int]列表中,您传递它想要的Int -> Int功能。 但部分地施加betaRest[Int] -> Int

至于[0..9]其类型是(Enum t, Num t) => [t]和它的翻译成enumFromTo 0 9应用。 所以编译器想通您的错误周围的其他方法:如果你定义特殊的NumEnum实例的列表,所以[0..9]变成为int的名单列表,那么你的应用程序将是有意义的。

但我认为你想使用initstails的功能。 让我们知道你想达到的,所以我们可以帮助解决什么。

一个最小的修复程序会增加prevDigits作为参数map和使用lambda抽象忽略未使用的prevDigit

   | otherwise = sum (map (\prevDigit -> betaRest (n - 1) [0..9]) prevDigits)


Answer 2:

(sum (map (betaRest (n - 1)) [0..9]))

让我们减少括号的数量,以便更好地能够看到发生了什么。

sum (map (betaRest (n - 1)) [0..9])

的说法sum

map (betaRest (n-1)) [0 .. 9]

现在, betaRest :: Int -> [Int] -> Int ,部分应用函数的,因此类型是

betaRest (n-1) :: [Int] -> Int

因此,我们可以推断出类型

map (betaRest (n-1)) :: [[Int]] -> [Int]

但传递的参数来map (betaRest (n-1))[0 .. 9]其类型为

[0 .. 9] :: (Num a, Enum a) => [a]

Num约束来自使用一个整数文字,和所述的Enum从使用的约束enumFromTo功能(在其语法糖形式[low .. high] )。 顺便指出,作为参数传递给期望类型的参数的函数[[Int]]指型变量a必须被实例化为[Int]然后需要被检查的制约,即,实例[Int]NumEnum必须抬起头来。 这些都不存在,因此错误消息。

我不知道你的程序的例子是你真正想要的东西,

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;
  }
}

foreach循环更容易(和更有效)表示为

sum = prevDigits.length * betaRest(n-1, [0 .. 9]);

因此对于foreach是有道理的,应该有一个依赖prevDigit在循环体。

翻译哈斯克尔会

betaRest n prevDigits
    | n == 0    = length prevDigits
    | otherwise = length prevDigits * betaRest (n-1) [0 .. 9]
    -- or with the loop, with the small improvement that `betaRest (n-1) [0 .. 9]
    -- is only computed once (if the Haskell implementation is sensible)
    -- | otherwise = sum $ map (const $ betaRest (n-1) [0 .. 9]) prevDigits

但如上所述,我怀疑这真的是你想要的。



文章来源: Haskell Error: \"No instance for (Enum [Int])