[英]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)’
您的大部分問題都是類型錯誤。 這些是編寫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你不應該使用或者do
或return
這里,而不是僅僅使用表達式,您擁有:
runGet getuint8 (drop startpos contents)
prelude中定義的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值,打印該值。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.