2015-10-22 3 views
4

Я написал то, что, по моему мнению, было бы общей функцией в Haskell, но я не мог найти ее реализованной нигде. Из-за лучшего слова я назвал его «трансформировать».Функция «преобразование» Haskell

Что «преобразование» содержит три аргумента: список и начальное состояние, а также функцию, которая принимает элемент из списка, состояние и создает элемент для выходного списка и новое состояние. Выходной список имеет ту же длину, что и список ввода.

Это похоже на «scanl», если он также принял параметр состояния или, например, «unfoldr», если вы можете подать его в список.

В самом деле, я реализовал эту функцию ниже, двумя различными способами, которые имеют один и тот же результат:

transform1 :: (b -> c -> (a, c)) -> c -> [b] -> [a] 
transform1 f init x = unfoldr f' (x, init) 
    where 
    f' ((l:ls), accum) = let (r, new_accum) = f l accum in Just (r, (ls, new_accum)) 
    f' ([], _) = Nothing 

transform2 :: (b -> c -> (a, c)) -> c -> [b] -> [a] 
transform2 f init x = map fst $ tail $ scanl f' init' x where 
    f' (_,x) y = f y x 
    init' = (undefined, init) 

Такого рода операции кажется довольно распространенным явлением, хотя, то есть, принимая список и ходить через него с некоторым состоянием и созданием нового списка, поэтому мне интересно, есть ли функция, которая уже существует, и я изобретаю колесо. Если это так, я просто использую это, но если нет, я могу упаковать то, что у меня есть (очень) небольшая библиотека.

+1

'mapAccumL' похоже на функцию, которую вы ищете. – snak

ответ

6

Это почти, но не точно Data.List.mapAccumL. Разница в том, что mapAccumL также включает в себя конечное состояние. Также он недавно получил обобщение на Traversable.

mapAccumL :: Traversable t => (a -> b -> (a, c)) -> a -> t b -> (a, t c) 
+0

Вот это ура! – Clinton

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