Ошибка синтаксического анализа лямбда-выражения на )

Моя задача - повторно реализовать эту функцию

divn :: Integer -> [Integer] -> [Integer]
divn _ [] = []
divn n (x:xs) | mod x n == 0 = x : divn n xs
              | otherwise = divn n xs

с помощью «папки». Что я сделал:

divn' _ [] = []
divn' n (x:xs) = foldr (\x -> if (mod x n == 0) (x:) ([]++)) [] xs

Я думал, что это сработает. На самом деле он даже не компилируется, а пишет: "Ошибка синтаксического анализа на входе").

Так как я не нашел ошибок, я решил переписать, как если бы, и теперь это работает...

if' True x _ = x
if' False _ x = x

divn' _ [] = []
divn' n (x:xs) = foldr (\x -> if' (mod x n == 0) (x:) ([]++)) [] xs

Кто-нибудь знает, где ошибка?

Спасибо!


person fsperrle    schedule 14.07.2012    source источник


Ответы (2)


if нужны then и else в Haskell,

(\x -> if (mod x n == 0) (x:) ([]++))

должно быть

(\x -> if (mod x n == 0) then (x:) else id)
person Daniel Fischer    schedule 14.07.2012

Помимо того, что сказал Дэниел Фишер, вам не нужны отдельные случаи: рекурсии нет, случай пустого списка будет обрабатываться foldr. В вашем коде первый x всегда игнорируется! Правильно

divn' n xs = foldr (\x -> if x`mod`n == 0 then (x:) else id) [] xs

или, по η-редукции,

divn' n = foldr (\x -> if x`mod`n == 0 then (x:) else id) []

Конечно, было бы гораздо более идиоматично просто сделать

divn'' n = filter ((==0) . (`mod`n))
person leftaroundabout    schedule 14.07.2012
comment
Правильно, он соответствует (x:xs), но никогда не использует x, а только другую переменную, которая случайно (или, я бы сказал, случайно) имеет такое же имя: параметр λ-функции, которая затеняет исходную x, фактически отбрасывая ее. - person leftaroundabout; 14.07.2012