试图通过Haskell中的偏移量读取字节(Word8)并获得各种错误(Trying to read a byte (Word8) by offset in Haskell and getting va

系统教程 行业动态 更新时间:2024-06-14 17:01:34
试图通过Haskell中的偏移量读取字节(Word8)并获得各种错误(Trying to read a byte (Word8) by offset in Haskell and getting various error)

我有一个名为test2.hs的文件,我正在尝试通过二进制文件中的偏移读取一个字节(Word8)并将其用作Int。 下面的例子是尝试读取二进制文件中的第二个字节。

import qualified Data.ByteString.Lazy as BS import Data.Word import Data.Bits import Data.Binary.Get getuint8 = do uint8 <- getWord8 return uint8 readuint8 :: BS.ByteString -> Int -> Int readuint8 contents startpos = do return $ runGet getuint8 (drop startpos contents) main :: IO () main = do let myfile = "DATA.BIN" contents <- BS.readFile myfile let stuff = readuint8 contents 1 print stuff

不太清楚为什么我得到以下错误:

test2.hs:12:9: error: • Couldn't match expected type ‘Int’ with actual type ‘m0 Word8’ • In a stmt of a 'do' block: return $ runGet getuint8 (drop startpos contents) In the expression: do { return $ runGet getuint8 (drop startpos contents) } In an equation for ‘readuint8’: readuint8 contents startpos = do { return $ runGet getuint8 (drop startpos contents) } test2.hs:12:35: error: • Couldn't match expected type ‘BS.ByteString’ with actual type ‘[a0]’ • In the second argument of ‘runGet’, namely ‘(drop startpos contents)’ In the second argument of ‘($)’, namely ‘runGet getuint8 (drop startpos contents)’ In a stmt of a 'do' block: return $ runGet getuint8 (drop startpos contents) test2.hs:12:49: error: • Couldn't match expected type ‘[a0]’ with actual type ‘BS.ByteString’ • In the second argument of ‘drop’, namely ‘contents’ In the second argument of ‘runGet’, namely ‘(drop startpos contents)’ In the second argument of ‘($)’, namely ‘runGet getuint8 (drop startpos contents)’

I have a file called test2.hs below where I'm trying to read a byte (Word8) by offset in a binary file and use it as Int. Below example is trying to read the 2nd byte in the binary file.

import qualified Data.ByteString.Lazy as BS import Data.Word import Data.Bits import Data.Binary.Get getuint8 = do uint8 <- getWord8 return uint8 readuint8 :: BS.ByteString -> Int -> Int readuint8 contents startpos = do return $ runGet getuint8 (drop startpos contents) main :: IO () main = do let myfile = "DATA.BIN" contents <- BS.readFile myfile let stuff = readuint8 contents 1 print stuff

Not too sure why I'm getting the below errors:

test2.hs:12:9: error: • Couldn't match expected type ‘Int’ with actual type ‘m0 Word8’ • In a stmt of a 'do' block: return $ runGet getuint8 (drop startpos contents) In the expression: do { return $ runGet getuint8 (drop startpos contents) } In an equation for ‘readuint8’: readuint8 contents startpos = do { return $ runGet getuint8 (drop startpos contents) } test2.hs:12:35: error: • Couldn't match expected type ‘BS.ByteString’ with actual type ‘[a0]’ • In the second argument of ‘runGet’, namely ‘(drop startpos contents)’ In the second argument of ‘($)’, namely ‘runGet getuint8 (drop startpos contents)’ In a stmt of a 'do' block: return $ runGet getuint8 (drop startpos contents) test2.hs:12:49: error: • Couldn't match expected type ‘[a0]’ with actual type ‘BS.ByteString’ • In the second argument of ‘drop’, namely ‘contents’ In the second argument of ‘runGet’, namely ‘(drop startpos contents)’ In the second argument of ‘($)’, namely ‘runGet getuint8 (drop startpos contents)’

最满意答案

输入错误

您的大部分问题都是类型错误。 这些是编写Haskell程序时最常见的编译器错误消息类型。 我们来看一个示例函数:

readuint8 :: BS.ByteString -> Int -> Int

此函数将接受ByteString和Int然后返回Int 。

readuint8 contents startpos

所以内容是ByteString , startpos是Int 。

= do return $

出于某种原因,您使用的是do notation,但类型( Int )不是monad(它看起来像IO Int , [Int]或更常见的m Int )。 问题1您不应该使用或return此处,而只是使用您拥有的表达式:

runGet getuint8 (drop startpos contents)

前奏中定义的drop函数在列表上运行,而不是ByteStrings。 问题2你可能想要BS.drop 。 由于bytestring drop需要一个与Int不同的Int64参数,因此您应该通过fromIntegral转换。 请注意,丢弃字节意味着startpos为零索引。

现在类型是......无论getuint8的类型是什么。 请注意,此函数定义是多余的 - 它等于getuint8 = getWord8 。 您没有显式键入getuint8 ,但推断类型为Get Word8 。 问题3 Word8和Int类型的混合是一个问题 - readuint8需要一个Int ,它与Word8不同。 您可以使用fromIntegral在整数类型之间进行转换,因此请考虑:

fromIntegral (runGet getuint8 (BS.drop (fromIntegral startpos) contents))

替代

考虑只是解压缩bytestring并索引到:

main :: IO () main = do let myfile = "DATA.BIN" contents <- BS.readFile myfile let stuff = drop 1 (BS.unpack contents) case stuff of (firstByte:restOfTheBytes) -> print firstByte [] {- empty list of bytes -} -> putStrLn "The file was not that long."

考虑一下原始结构的轻微压实:

main :: IO () main = print . runGet getWord8 . BS.drop 1 =<< BS.readFile "DATA.BIN"

其中从右到左读取文件,删除一个字节,获取第一个Word8值,打印该值。

Type Errors

Most of your issues are type errors. These are the most common type of compiler error message when writing a Haskell program. Let's look at an example function:

readuint8 :: BS.ByteString -> Int -> Int

This function will accept a ByteString and Int then return an Int.

readuint8 contents startpos

So contents is the ByteString and startpos is the Int.

= do return $

For some reason you are using do notation, but the type (Int) is not a monad (which would appear as something like IO Int, [Int] or more generally m Int). Issue 1 You should not be using either do or return here and instead just use the expression, for which you have:

runGet getuint8 (drop startpos contents)

The drop function defined in the prelude operates over lists, not ByteStrings. Issue 2 You probably want BS.drop. Since bytestring drop requires an Int64 parameter, which is distinct from an Int, you should convert via fromIntegral. Note that dropping bytes implies startpos is zero indexed.

Now the type is... whatever getuint8's type is. Notice this function definition is superfluous - it is equal to getuint8 = getWord8. You didn't explicitly type getuint8, but the type is inferred to be a Get Word8. Issue 3 The mixing of Word8 and Int types is a problem - readuint8 expects an Int and that is different than Word8. You can convert between integral types using fromIntegral so consider:

fromIntegral (runGet getuint8 (BS.drop (fromIntegral startpos) contents))

Alternative

Consider just unpacking the bytestring and indexing into that:

main :: IO () main = do let myfile = "DATA.BIN" contents <- BS.readFile myfile let stuff = drop 1 (BS.unpack contents) case stuff of (firstByte:restOfTheBytes) -> print firstByte [] {- empty list of bytes -} -> putStrLn "The file was not that long."

Consider some slight compaction of your original construction:

main :: IO () main = print . runGet getWord8 . BS.drop 1 =<< BS.readFile "DATA.BIN"

Which reads from right to left as read the file, drop a byte, get the first Word8 value, print the value.

更多推荐

本文发布于:2023-04-20 18:51:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/dzcp/36c6ea8713877f91e08d2b204b2aae31.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:字节   错误   偏移量   Haskell   byte

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!