haskell中具有多参数函数的惰性过滤器
我正在编写一个函数来删除json字符串中的空白。我 需要知道我正在处理的当前字符是否被haskell中具有多参数函数的惰性过滤器,haskell,functional-programming,Haskell,Functional Programming,我正在编写一个函数来删除json字符串中的空白。我 需要知道我正在处理的当前字符是否被“包围,或者 如果它在转义字符\之后,那么我还需要两个参数 功能 这是当前的实现。但我不认为它是懒惰的。如何实现呢 我可以用json字符串上的“filter”或“map”使它变懒吗 compressJson :: String -> String compressJson json = compress json False False "" -- compress params: json, i
“
包围,或者
如果它在转义字符\
之后,那么我还需要两个参数
功能
这是当前的实现。但我不认为它是懒惰的。如何实现呢
我可以用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]
这实际上是微不足道的懒惰-不要让它尾部递归 差不多是这样(我没有测试)
尾部递归和惰性是直接对立的。尾部递归意味着一个函数是使用修改的参数对其自身的调用。惰性意味着它会立即返回一个构造函数(即,不是在不确定的递归调用次数之后)。因此,如果您希望函数是惰性的,请编写它以立即返回部分结果。这实际上是一个很小的惰性-不要使其尾部递归 差不多是这样(我没有测试) 尾部递归和惰性是直接对立的。尾部递归意味着一个函数是使用修改的参数对其自身的调用。惰性意味着它会立即返回一个构造函数(即,不是在不确定的递归调用次数之后)。因此,如果您希望函数是惰性的,请编写它以立即返回部分结果。问题中的“惰性”一词表示我们希望函数“对输入的强制最小,对输出的影响最大”。在“Haskell的惰性求值”中使用了同一个词,因此可能会造成混淆 生产函数可以使用中的保护递归进行编码。它遵循
foldr
模式w.r.t.输入字符串,但foldl
w.r.t.其他2个参数。换句话说,它从右到左构造输出,但要这样做,它需要从左到右传递控制参数。因此,操作问题是f如何使用(“使用过滤器使其变懒
或映射
…”)对其进行编码
受保护的递归与之密切相关。核心递归基本上是展开的。递归是“返回”,但核心递归是“前进”。输入的逐步消耗,一点一点地,也可以被视为“前进”。因此,我们将使用展开器
,并使用concat
消耗其输出(以适应跳过的需要,或有时在输出中生成多个元素)
因此,通过纯粹的机械操作,我们可以从清晰易读的公式中获得高效的代码,因为您使用的累积参数技术是迭代的表达式,正如corecursion也是:
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))
另见:
foldr
模式w.r.t.输入字符串,但foldl
w.r.t.其他2个参数。换句话说,它从右到左构造输出,但要这样做,它需要从左到右传递控制参数。因此,操作问题是f如何使用(“使用过滤器使其变懒
或映射
…”)对其进行编码
受保护的递归与之密切相关。核心递归基本上是展开的。递归是“返回”,但核心递归是“前进”。输入的逐步消耗,一点一点地,也可以被视为“前进”。因此,我们将使用展开器
,并使用concat
消耗其输出(以适应跳过的需要,或有时在输出中生成多个元素)
因此,通过纯粹的机械操作,我们可以从清晰易读的公式中获得高效的代码,因为您使用的累积参数技术是迭代的表达式,正如corecursion也是:
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))
另见:
反向
将强制输出通过-因此这与OP要求的相反。-“多个元素”通常通过concatMap::(a->[b])->[a]->[b]处理
@user2407038如果您按照您所说的方式进行更改,但保持尾部递归,它仍然会强制整个输入通过;然后使用反向
将强制输出通过-因此这与OP要求的相反。-“多个元素”通常通过concatMap::(a->[b])->[a]->[b]
处理。