Не удалось сопоставить ожидаемый тип " 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 решит, что ваш буквально написано 0
s - это любой числовой тип, необходимый для этой работы,предоставил есть 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