2015-10-13 3 views
1

Я следующий код (связанный с проблемой Project Эйлера 34):Почему этот код Haskell не работает?

fac :: Int -> Int 
fac = foldr1 (*) . enumFromTo 1 

fe :: Int -> Bool 
fe = (==) =<< (sum . map fac . digits 10) 

fes :: [Int] 
fes = filter fe [3..] 

fac работает отлично, fe работает отлично, но fes дает:

*** Exception: Prelude.foldr1: empty list 

Интересно, что если я начну список с 145 (fe возвращает True здесь), он работает для этого числа, а затем вызывает исключение.

Почему этот код не работает? Это похоже на совершенно нормальное применение filter с четко функционирующей функцией и регулярным списком номеров, которые работают с этой функцией по отдельности.

+1

Ваш код полон точной нечитаемости. Так или иначе, 'fac' вызывается с аргументом меньше 1, заставляя аргумент list' foldr1' (ужасно теневая функция) быть пустым. – dfeuer

+3

@dfeuer Ба, я думаю, что только трудночитаемая часть - это '(==) = <<'. –

+1

@ ØrjanJohansen Я бы не стал писать так, как в фактическом «производственном» коде; Я делаю такие упражнения в основном для экспериментов с Haskell. То же самое касается использования 'foldr1 (*)' вместо 'product'; ваш вопрос о 'foldl'' vs' foldr', и точка @ dfeur 'shadiness' of 'foldr1', безусловно, хорошая. Если бы я использовал «продукт» здесь, я бы не столкнулся с этой проблемой, но я бы тоже не узнал об этом. :) – Ben

ответ

6

Ваш fac с ошибкой 0, для которого его список пуст. Вы можете попробовать

fac = foldr (*) 1 . enumFromTo 1 

Кстати foldl' (от Data.List), вероятно, лучше, чем foldr здесь, также есть предопределенные product функция.

Смежные вопросы