haskell中具有多参数函数的惰性过滤器

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字符串中的空白。我 需要知道我正在处理的当前字符是否被
包围,或者 如果它在转义字符
\
之后,那么我还需要两个参数 功能

这是当前的实现。但我不认为它是懒惰的。如何实现呢 我可以用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))
另见:

问题中的“懒惰”一词意味着我们想要一个“对输入的强制最小,对输出的效率最高”的函数。“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))
另见:


@user2407038如果您按照您所说的方式进行更改,但保持尾部递归,它仍然会强制整个输入通过;然后使用
反向
将强制输出通过-因此这与OP要求的相反。-“多个元素”通常通过
concatMap::(a->[b])->[a]->[b]处理
@user2407038如果您按照您所说的方式进行更改,但保持尾部递归,它仍然会强制整个输入通过;然后使用
反向
将强制输出通过-因此这与OP要求的相反。-“多个元素”通常通过
concatMap::(a->[b])->[a]->[b]
处理。