簡體   English   中英

試圖通過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)’

輸入錯誤

您的大部分問題都是類型錯誤。 這些是編寫Haskell程序時最常見的編譯器錯誤消息類型。 我們來看一個示例函數:

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

此函數將接受ByteStringInt然后返回Int

readuint8 contents startpos 

所以內容是ByteStringstartposInt

       = do
    return $ 

出於某種原因,您使用的是do notation,但類型( Int )不是monad(它看起來像IO Int[Int]或更常見的m Int )。 問題1你不應該使用或者doreturn這里,而不是僅僅使用表達式,您擁有:

runGet getuint8 (drop startpos contents)

prelude中定義的drop函數在列表上運行,而不是ByteStrings。 問題2你可能想要BS.drop 由於bytestring drop需要一個與Int不同的Int64參數,因此您應該通過fromIntegral轉換。 請注意,丟棄字節意味着startpos為零索引。

現在的類型是......無論getuint8的類型是什么。 請注意,此函數定義是多余的 - 它等於getuint8 = getWord8 您沒有顯式鍵入getuint8 ,但推斷類型為Get Word8 問題3 Word8Int類型的混合是一個問題 - 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM