Слово «ленивый» в вопросе означает, что нам нужна функция, которая «наименее вынуждает на входе и наиболее продуктивна на выходе». То же слово используется в «ленивой оценке» Хаскелла, так что это может сбивать с толку.
Производственные функции могут быть закодированы с охраняемой рекурсией, как в Carl's great answer. Это следует за рисунком foldr
w.r.t. входная строка, но foldl
w.r.t. другие 2 параметра. Другими словами, он строит свой вывод справа налево, но для этого ему нужно передать контрольные параметры слева направо. Следовательно, вопрос OP о том, как кодировать это с помощью HOF (), делает его ленивым с filter
или map
... ").
Охраняемая рекурсия тесно связана с corecursion. Corecursion, в основном, разворачивается. Рекурсия «возвращается», но кокуркация «идет вперед». Постепенное потребление ввода поэтапно можно рассматривать как «движение вперед» вдоль него. Таким образом, мы будем использовать unfoldr
и потребляем его выход с concat
(чтобы удовлетворить необходимость пропуска или иногда производить более одного элемента на выходе).
Таким образом, мы получаем эффективный код с четким и легко читаемым рецептура с помощью чисто механическими манипуляциями, так как накапливая техник аргумента вы использовали это выражение итерации, так же, как корекурсия слишком:
import Data.List (unfoldr)
compressJson :: String -> String
compressJson json = -- g json False False ""
concat $ unfoldr h (json,False,False)
where
{- g params: json, inStr, aferEscape, acc
g [] _ _ acc = acc
g ('\"' : xs) inStr False acc = g xs (not inStr) False (acC++ "\"")
g ('\\' : xs) inStr False acc = g xs inStr True acc
g (x : xs) inStr True acc = g xs inStr False (acC++ ['\\', x])
g (x : xs) True False acc = g xs True False (acC++ [x])
g (x : xs) False _ acc = g xs False False (acC++ parse x)
-}
parse c = [c | not (c `elem` " \t\n")]
h ([] , _ , _ ) = Nothing
h ('\"' : xs, inStr, False) = Just ("\"", (xs, not inStr, False))
h ('\\' : xs, inStr, False) = Just ([] , (xs, inStr, True))
h (x : xs, inStr, True) = Just (['\\', x],(xs, inStr, False))
h (x : xs, True , False) = Just ([x], (xs, True, False))
h (x : xs, False, _ ) = Just (parse x, (xs, False, False))
Смотри также:
@ user2407038, если вы вносите изменения, как вы говорите, но оставляете хвост рекурсивным, он все равно будет вынуждать весь ввод; а затем с помощью 'reverse' будет принудительно выводить результат - так что это противоположность тому, что просит OP. - «несколько элементов» обычно обрабатываются через 'concatMap :: (a -> [b]) -> [a] -> [b]'. –