我正在编写一个删除json字符串中的空格的函数。一世
需要知道我正在处理的当前字符是否被"
包围,或者
如果它是在转义字符\
之后。所以我需要两个更多的参数
功能
这是当前的实施。但我不认为这是懒惰的。怎么样 我可以在json字符串上使用“filter”或“map”使其变得懒惰吗?
compressJson :: String -> String
compressJson json = compress json False False ""
-- compress params: json, inStr, aferEscape, acc
where compress [] _ _ acc = acc
compress ('\"' : xs) inStr False acc = compress xs (not inStr) False (acc ++ "\"")
compress ('\\' : xs) inStr False acc = compress xs inStr True acc
compress (x : xs) inStr True acc = compress xs inStr False (acc ++ ['\\', x])
compress (x : xs) True False acc = compress xs True False (acc ++ [x])
compress (x : xs) False _ acc = compress xs False False (acc ++ parse x)
parse c = if c `elem` " \t\n"
then []
else [c]
答案 0 :(得分:9)
这实际上是无聊的 - 不要让它拖尾递归。
或多或少这样(我没有测试过)
compressJson :: String -> String
compressJson json = compress json False False
-- compress params: json, inStr, aferEscape
where compress [] _ _ = ""
compress ('\"' : xs) inStr False = '\"' : compress xs (not inStr) False
compress ('\\' : xs) inStr False = compress xs inStr True
compress (x : xs) inStr True = '\\' : x : compress xs inStr False
compress (x : xs) True False = x : compress xs True False
compress (x : xs) False _ = parse x ++ compress xs False False
parse c = if c `elem` " \t\n"
then []
else [c]
尾巴递归和懒惰是彼此直接的可能性。尾递归意味着函数是使用修改后的参数调用自身。懒惰意味着它会立即返回一个构造函数(即,不是在一些不确定的递归调用之后)。因此,如果您希望函数是惰性的,请将其写入以立即返回部分结果。
答案 1 :(得分:2)
问题中的“懒惰”一词意味着我们想要一个“最小化输入并且输出效率最高”的函数。在“Haskell的懒惰评估”中使用了相同的单词,因此可能会令人困惑。
生成函数可以使用保护递归进行编码,如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))
另见: