В дополнение к ошибке типа в lessen
у вас есть логическая ошибка в простых числах:
length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2
Вы (справедливо) рассматриваете элементы только до lessen x
.Это приводит к тому, что в списке почти никогда не будет ровно x - 2
элементов.Как следствие, вы попадете в бесконечный цикл при попытке получить более двух элементов из этого списка (потому что нет 3-го элемента, для которого выполняется условие, но haskell не знает этого, поэтому он переходит к бесконечности, пытаясьчтобы найти его).
Также обратите внимание, что взятие длины списка - это операция O(n)
, и почти всегда есть лучший способ добиться того, чего вы хотите.
Как примечание стиля,Я бы порекомендовал определить отдельный метод isPrime.Это заставит ваш код выглядеть так:
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
isPrime x = length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
primes :: [Int]
primes = [x| x <- [1..], isPrime x]
lessen :: Int -> Int
lessen a = ceiling(sqrt (fromIntegral a))
Это ИМХО делает понимание списка намного более читабельным.Однако это все еще содержит ошибку.Чтобы избавиться от ошибки, я бы предложил определить isPrime, используя другой подход.Достигнуть до lessen x
хорошо (за исключением того, что вы должны начинать с 2, потому что 1 аккуратно делит все), но вместо создания нового списка со всеми делителями, вы должны просто проверить, делит ли любое из чисел в диапазоне x.Для этого мы можем использовать функцию высшего порядка any
, поэтому получаем:
isPrime x = not (any (\a -> mod x a == 0) [2 .. lessen x])