具有haskell中的多参数函数的延迟过滤器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了具有haskell中的多参数函数的延迟过滤器相关的知识,希望对你有一定的参考价值。

我正在编写一个删除json字符串中的空格的函数。我需要知道我正在处理的当前char是否被"包围,或者它是否在一个转义字符之后。所以我需要两个param用于此功能。

这是当前的实现。但我不认为这是懒惰的。如何在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` " 	
"
              then []
              else [c]
答案

这实际上是微不足道的懒惰 - 不要让它尾递归。

或多或少这样(我没有测试过)

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` " 	
"
              then []
              else [c]

尾递归和懒惰是彼此直接的可能性。尾递归意味着函数是使用修改后的参数调用自身。懒惰意味着它会立即返回一个构造函数(即,不是在一些不确定的递归调用之后)。因此,如果您希望函数是惰性的,请将其写入以立即返回部分结果。

另一答案

问题中的“懒惰”一词意味着我们想要一个“在输入上最小化并且在输出中效率最高”的函数。在“Haskell的懒惰评估”中使用了相同的单词,因此可能会令人困惑。

生成函数可以使用Carl's great answer中的保护递归进行编码。它遵循foldr模式w.r.t。输入字符串,但是foldl w.r.t.其他2个参数。换句话说,它从右到左构造它的输出,但是为了这样做,它需要从左到右传递控制参数。因此OP的问题是如何使用HOF对其进行编码(“使其与filtermap使其变得懒惰......”)。

守卫递归与corecursion密切相关。 Corecursion基本上正在展开。递归是“回归”,但核心运动是“前进”。逐渐消耗输入,也可以看作是沿着它“前进”。所以我们将使用unfoldr,并使用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` " 	
")]

    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中的多参数函数的延迟过滤器的主要内容,如果未能解决你的问题,请参考以下文章

函数返回与函数参数中的 Haskell 模式匹配

Haskell 在 Scala 中的新类型

django中具有多个参数的过滤器和链式过滤器之间的区别

Haskell 中的参数化类型

Swift 之惰性求值

Haskell缩进不会排列函数参数