[Haskell]fold vs. не fold
От: Mr.Cat  
Дата: 01.02.08 22:40
Оценка:
Допустим, нам надо произвести некое относительно простую "агрегирующую" операцию над списком. С одной стороны, специально для этого есть функции fold*. С другой стороны — можно просто реализовать рекурсивную функцию. Но как лучше поступить? Есть ли какие-либо подводные камни? Не считается ли моветоном неиспользование fold* там, где его логично использовать?

Чтобы не быть голословным — вот пример. Пусть у нас стоит такая задача (взята из викикнижки по хаскелю):

Implement a function sequenceIO :: [IO a] -> IO [a]. Given a list of actions, this function runs each of the actions in order and returns all their results as a list.

Авторы предлагают такое решение — без fold
sequenceIO :: [IO a] -> IO [a]
sequenceIO [] = return []
sequenceIO (a:as) = do {v <-a ; vs <- (sequenceIO as) ; return (v : vs)}

То же самое можно сделать, допустим с foldr (т.к., насколько я понимаю, здесь возможны ленивые вычисления, поправьте, если это не так)
sequenceIO :: [IO a] -> IO [a]
sequenceIO = foldr (\io acc -> do {x<-io; xs<-acc; return (x:xs) }) (return [])

Строчек (и букв) меньше (в полтора раза ). И вроде чуть более читабельно.

Вот мои мысли. Есть такой паттерн — "агрегирующая функция" (не знаю, как правильно назвать). И fold* — "хелперы" для этого паттерна. Они, может, не всегда полезны для самого разработчика, но код читать помогают (собственно, это ко многим подобным функциям относится: scan*, map и т.п.).

PS: Или мне просто пора немного отдохнуть?
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.