3

我正在编写一个对ByteString值列表进行操作的 Haskell 函数。我需要对第一个和最后一个项目执行不同的操作(如果列表只有一个项目,这可能是相同的)。

具体来说,我想写出以下内容:

  "item-1\
  \item-2\
  \item-3\
  ...
  \item-n"

其中item-1以双引号开头并以item-n反斜杠结尾并以反斜杠开头并以双引号结尾。item-1和之间的所有项目都item-n以反斜杠开始和结束。我将 base64 编码值作为 Haskell 发出以String进行某些代码生成。我已经将原始(长)base64 编码ByteString分解为每个 64 个字符长的块。

4

4 回答 4

11

我才意识到我的问题是一个愚蠢的问题。

我可以只使用在项目之间intercalate注入"\\\n\\",然后在前面加上双引号:

import qualified Data.ByteString.Lazy.Char8 as L
(L.pack "\"") `L.append` (L.intercalate "\\\n\\" items) `L.append` (L.pack "\"")

样本输出:

"H4sIAAAAAA\
\AAA2NgAAMm\
\CMXA7JRYxI\
\Am5JafD2Uy\
\AgDvdHs6Lg\
\AAAA==\
\"
于 2013-01-01T20:52:06.347 回答
2

您还可以考虑使用以下方法拆分列表:

  • "head" 获取列表的第一个元素
  • "tail" 获取列表中除第一个元素之外的所有元素
  • "init" 获取列表中除最后一个元素之外的所有元素
  • "last" 获取列表的最后一个元素

所以[head a] ++ init (tail a) ++ [last a] == a

这样,您可以单独更改列表的第一个和最后一个元素,并将函数映射到“init”部分。

于 2013-01-01T23:00:18.190 回答
0

我曾多次遇到这种情况,但从未找到一个好的惯用解决方案。有时intercalate还不够。这是一个简单的解决方案。

-- | Annotate elements of a list with Bools, the first of which is True if
-- the element is the head of the list, the second of which is True if the
-- element is the last of the list. Both are True for singleton.
markbounds :: [a] -> [(a, Bool, Bool)]
markbounds [] = []
markbounds [x] = [(x, True, True)]
markbounds (x:xs) = (x, True, False) : tailbound xs
  where
    tailbound [y] = [(y, False, True)]
    tailbound (y:ys) = (y, False, False): tailbound ys

例如:

λ> markbounds [1,2,3]
[(1,True,False),(2,False,False),(3,False,True)]

λ> forM_ (markbounds [1,2,3]) $ \(x, isFirst, isLast) -> when isLast $ print x
3
于 2018-11-13T13:53:45.330 回答
0

我已经构建了(我的第一个!)库,它对“不同的第一个和最后一个函数”问题有一个合理通用的解决方案。它在 GitHub ( https://github.com/davjam/MapWith ) 和 Hackage ( http://hackage.haskell.org/package/MapWith ) 上。

最初受到 James 的 markbounds 函数的启发,但可以:

  • 处理比列表更通用的结构(所有 Traversable 类型)
  • 直接向函数添加参数(不仅仅是创建元组)
  • 添加不同类型的参数(第一个/最后一个/下一个元素/上一个元素/从开始或结束的索引等)
  • 允许创建其他类型的参数。
  • 添加任意数量的参数

例如:

> andFirstLast [1,2,3]
[(1,True,False),(2,False,False),(3,False,True)]

> mapWithM_ ((\x isL -> when isL $ print x) & isLast) [1,2,3]
3

> mapWith ((,,,) & isLast & prevElt <-^ eltIx) [1,7,4]
[(1,False,Nothing,2),(7,False,Just 1,1),(4,True,Just 7,0)]

更多示例见 https://github.com/davjam/MapWith/blob/master/doc/examples.hs

任何反馈将不胜感激。谢谢!

于 2019-01-23T15:11:56.113 回答