3

我得到了这个代码,它接受一个整数“n”和一个列表,然后将列表拆分为“n”个列表。

chunk n xs = chunk' i xs
  where
    chunk' _ [] = []
    chunk' n xs = a : chunk' n b where (a,b) = splitAt n xs
    i = ceiling (fromIntegral (length xs) / fromIntegral n)

这是它如何工作的一个例子:

*Main> chunk 5 [1..10]
[[1,2],[3,4],[5,6],[7,8],[9,10]]

我一直试图让它与 Data.ByteString 库一起使用,但无法弄清楚。

这是我一直在尝试使用的代码。

import qualified Data.ByteString as B
B.readFile "meow.txt" >>= (\x -> return $ chunk 4 x)

这是它给我的错误:

<interactive>:402:51:
    Couldn't match expected type `[a10]'
                with actual type `B.ByteString'
    In the second argument of `chunk', namely `x'
    In the second argument of `($)', namely `chunk 4 x'
    In the expression: return $ chunk 4 x

这似乎是一个类型不匹配的问题,我假设是因为fromIntegral. 有没有办法让块函数接受字节字符串?

我使用此功能的目标是严格接受任意长度的二进制文件,然后将其拆分为长度大致相等的 4 段,而不会丢失过程中的任何数据。

4

4 回答 4

4

字节字符串不是列表。您将不得不编写一个单独的函数。

但这是一个简单的翻译。假设你有import qualified Data.ByteString as B,那么

chunkBytes :: Int -> B.ByteString -> [B.ByteString]
chunkBytes n xs = chunk' i xs
  where
    chunk' n xs
        | B.null xs = []
        | otherwise = a : chunk' n b where (a,b) = B.splitAt n xs
    i = ceiling (fromIntegral (B.length xs) / fromIntegral n)
于 2012-11-04T15:10:10.867 回答
3

您也可以使用listlike包。它创建了一个统一的 API 来处理列表、ByteStringsText等。所以你可以这样写:

import qualified Data.ListLike as LL

chunk :: (Integral n, LL.ListLike l a) => n -> l -> [l]
chunk n xs = chunk' i xs
  where
    chunk' n xs | LL.null xs = []
                | otherwise = a : chunk' n b where (a,b) = LL.splitAt n xs
    i = ceiling (fromIntegral (LL.length xs) / fromIntegral n)
于 2012-11-04T16:23:08.223 回答
1

ByteString 不是一个列表,所以你不能用它来遍历它Prelude.splitAt,它是从 Data.List 导出的,你应该使用它B.splitAt

于 2012-11-04T15:10:47.853 回答
0

模式匹配是低级的,它严格使用值构造函数来匹配它。[] 和 (:) 是列表类型 [a] 的值构造函数。字节串构造器是不同的,通常对用户不是很有用。

我们已经看到对基于值的形状的更高级别匹配形式的一些兴趣,例如“可遍历”值。但据我所知,目前还没有任何实现。

于 2012-11-05T10:51:18.860 回答