繁体   English   中英

无法将预期类型“Int”与实际类型“Integer”匹配

[英]Couldn't match expected type `Int' with actual type `Integer'

我有以下Haskell代码:

-- Problem 69

import ProjectEuler

phi :: Integer -> Integer
phi n = n * product [p - 1 | p <- primeDivisors n] `div` product [p | p <- primeDivisors n]
-- primeDivisors n is a list of the prime divisors of n

maxRatio :: (Int, Int, Double) -> (Int, Int, Double) -> (Int, Int, Double)
maxRatio t1@(_, _, x) t2@(_, _, y)
  | x > y = t1
  | otherwise = t2

main = print (foldl
                maxRatio
                (0, 0, 0.0)
                [(n, phi n, ratio) | n <- [2..max], let ratio = fromIntegral n / (fromIntegral (phi n))]
              )
    where max = 1000

这给出了以下错误:

Couldn't match expected type `Int' with actual type `Integer'
In the expression: n
In the expression: (n, phi n, ratio)
In the third argument of `foldl', namely
  `[(n, phi n, ratio) |
      n <- [2 .. max],
      let ratio = fromIntegral n / (fromIntegral (phi n))]'

我怀疑在三元组(0, 0, 0.0) ,0是Int类型。 在这种情况下, 0总是输入Int还是ghci将类型推断为Int 如果是后者,我该如何强制它输入Integer 或者是否有其他原因会导致此错误?

Haskell通常可以推断出数字文字的类型,例如0就像你需要它们一样合适的类型。 这是因为它知道你传递给他们的功能; 如果我有一个函数phi :: Integer -> Integer ,我调用phi 0 ,Haskell知道那个特定的0必须是一个Integer 如果我用pho 0调用函数pho :: Int -> Int也没关系; 特定0被推断为一个Int

但是IntInteger是不同的类型,并且不能将特定的0传递给phipho

你的问题只是maxRatio处理的元组是由你输入的( (Int, Int, Double) ,但是这样的元组被构造为(n, phi n, ratio) 由于phi接受并返回Integer ,因此该表达式中的n必须是Integer 但是那对maxRatio ,所以你得到了错误。

根据您实际想要的类型( IntInteger ),您需要做的就是更改phimaxRatio的类型签名,以便它们使用相同类型的数字。 Haskell将决定你的字面上写的0是什么数字类型是必要的,以使其工作, 只要有一个可以使它工作!

需要注意的是传递消息的错误明确告诉你,这是n(n, phi n, ratio)这是预计的Int和实际上是一个Integer 永远不会提到(0, 0, 0.0)元组。 通常,类型错误源于编译器指向您的位置以外的其他位置(因为编译器可以做的就是发现不同的推理链对某些类型的类型产生不一致的要求,无法知道整个过程的哪个部分是“错误的” ),但在这种情况下,它做得很好。

Haskell得到了一个(相当合理的)糟糕的代表,因为它不可思议的错误消息,但它可以帮助很多东西从编译器告诉你的问题开始,并试图弄清楚为什么它的抱怨来自你的代码。 这一开始会很痛苦,但是你会很快在Haskell的错误消息(至少是更直接的错误消息)中开发一个基本知识,这将有助于你真正快速地发现这些类型的错误,这使编译器成为一个非常强大的错误检测系统为你服务。

由于maxRatio的类型, n被推断为Int ,而phi的类型则表示它应该是Integer 最简单的解决方法是将maxRatio的类型maxRatio为使用Integer ,甚至只更改a因为它不会触及这些值。

它是推断的,所以你可以改变maxRatio的类型签名。 但是,如果您需要将显式Int更改为Integer ,请使用toInteger :: (Integral a) => a -> Integer

您的类型签名不一致 - 始终将Int替换为Integer

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM