Не удалось сопоставить ожидаемый тип " Int "с фактическим типом "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. Is 0 всегда типа Int или ghci выводит тип как Int в этом случае? Если позже, как заставить его быть типом Integer вместо? Или есть что-то еще, что вызывает эту ошибку?

4 ответов


Haskell обычно может вывести тип числовых литералов, таких как 0 Как любой соответствующий тип, который вам нужен. Это потому, что он знает, какие функции вы передаете им; если у меня есть функция phi :: Integer -> Integer, а я называю phi 0, Хаскелл знает, что именно 0 должно быть Integer. Также нормально, если я вызываю функцию pho :: Int -> Int С pho 0; это особенности 0 выводится сообщение Int.

Int и Integer разные типы, и нет никакого способа одного конкретного 0 можно передавать как phi и pho.

ваша проблема заключается просто в том, что кортежи, которые maxRatio сделки с набираются (вами)(Int, Int, Double), но этот один такой кортеж построен как (n, phi n, ratio). С phi забирает и возвращает Integer, the n в этом выражении должно быть Integer. Но тогда это не работает для maxRatio, поэтому вы получаете ошибку.

в зависимости от того, какой тип вы на самом деле хотел (Int или Integer), все, что вам нужно сделать, это изменить сигнатуру типа phi или maxRatio так что они работают с одним и тем же номером. Haskell решит, что ваш буквально написано 0s - это любой числовой тип, необходимый для этой работы,предоставил есть can заставить его работать!

обратите внимание, что ошибка messaged конкретно я же говорил, что это n на (n, phi n, ratio) что было должна быть Int и был на самом деле Integer. The (0, 0, 0.0) кортеж никогда не упоминается. Часто ошибки типа возникают где-то, кроме того, где компилятор указывает на вас (поскольку все, что может сделать компилятор, - это определить, что различные цепочки вывода создают непоследовательные требования к типу чего-то, без возможности узнать, какая часть всего процесса "неправильная"), но в этом случае это было довольно хорошо.

Haskell получает (довольно оправданную) плохую репутацию за непостижимую ошибку сообщения, но это может помочь много начать с того, что компилятор говорит вам, это проблема и попытаться выяснить почему факты он жалуется возникнуть из кода. Сначала это будет болезненно, но вы быстро разовьете базовую грамотность в сообщениях об ошибках Haskell (по крайней мере, более простые), которые помогут вам быстро обнаружить такие ошибки, что делает компилятор очень мощной системой обнаружения ошибок для вас.


n выводится как Int из-за типа maxRatio тип phi говорит, что он должен быть!--4-->. Самое простое исправление-изменить тип maxRatio использовать Integer или даже просто a поскольку он не касается этих значений.


это выводится, поэтому вы можете просто изменить сигнатуру типа maxRatio. Тем не менее, если вам когда-либо нужно изменить явное Int до Integer используйте toInteger :: (Integral a) => a -> Integer


ваши подписи типа несовместимы-replace Int с Integer на протяжении.