我有这个代码,它接受一个整数'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个大致相等的长度,而不会丢失过程中的任何数据。
答案 0 :(得分: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)
答案 1 :(得分:3)
您也可以使用listlike包。它创建了一个统一的API来处理列表ByteString
,Text
等等。所以你可以这样写:
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)
答案 2 :(得分:1)
ByteString不是列表,因此您无法使用从Data.List导出的Prelude.splitAt
遍历它,您应该使用B.splitAt
。
答案 3 :(得分:0)
模式匹配是低级的,它严格使用值构造函数来匹配它。 []和(:)是列表类型[a]的值构造函数。 Bytestrings构造函数是不同的,通常对用户没有用。
我们已经看到了一些基于值的形状的更高级别匹配形式的兴趣,例如“可遍历”值。但据我所知,还没有任何实施。