Если вы пишете свою функцию немного по-другому, становится более очевидным, как превратить ее в foldr
. А именно:
myProduct :: (Eq n, Num n) => [n] -> n
myProduct = flip go 1 where
go (x:xs) = if x == 0 then \acc -> 0 else \acc -> acc `seq` go xs (acc * x)
go [] = \acc -> acc
Теперь go
имеет этот foldr
аромат, и мы можем просто заполнить отверстия.
myProduct :: (Foldable t, Eq n, Num n) => t n -> n
myProduct = flip go 1 where
go = foldr
(\x f -> if x == 0 then \acc -> 0 else \acc -> acc `seq` f (acc * x))
(\acc -> acc)
Надеюсь, вы сможете увидеть, откуда взялись все эти кусочки в предыдущем стиле явной рекурсии и насколько механическим является преобразование. Тогда я бы сделал несколько эстетических настроек:
myProduct :: (Foldable t, Eq n, Num n) => t n -> n
myProduct xs = foldr step id xs 1 where
step 0 f acc = 0
step x f acc = f $! acc * x
И мы все сделали! Небольшое быстрое тестирование в ghci показывает, что оно все еще замыкается на 0
по мере необходимости и использует постоянный пробел.