从Data.Binary.Get返回列表

时间:2013-03-14 14:27:09

标签: haskell binaryfiles

我正在尝试将MIDI文件作为处理二进制文件的教育练习,但我遇到了麻烦。

当我读取曲目时,我想只抓取文件标题部分中声明的特定数量的曲目。这是我的代码,我试图解决它(虽然不起作用):

getMidi = do
  header <- grabHeader
  tracks <- grabTracks (numTracks header)
  return (header, tracks)

grabTracks :: Integer -> Get [Track]
grabTracks numT = do
  if numT == 0
     then do
       return []
     else do
       myTrack <- grabTrack
       otherTracks <- grabTracks (numT-1)
       return myTrack : otherTracks

grabTrack :: Get Track
grabTrack = do
  chunkId <- getByteString 4
  chunkSize <- getWord32be
  events <- getLazyByteString (fromIntegral chunkSize)
  return Track {trackSize=(fromIntegral chunkSize), eventData=events}

numT是头文件中声明的曲目数。我想这样做有两个原因。

  1. 最后我可能会忽略垃圾。
  2. 想要将此技术应用于其中包含“somethings”列表的其他二进制文件。
  3. 当我尝试编译它时,我收到此错误:

    Couldn't match expected type `Get [a]' with actual type `[a0]'
        In a stmt of a 'do' block: return myTrack : otherTracks
        In the expression:
          do { myTrack <- grabTrack;
               otherTracks <- grabTracks (numT - 1);
               return myTrack : otherTracks }
        In a stmt of a 'do' block:
          if numT == 0 then
              do { return [] }
          else
              do { myTrack <- grabTrack;
                   otherTracks <- grabTracks (numT - 1);
                   return myTrack : otherTracks }
    

    当我被迫使用像这样的列表连接时,我不知道如何制作Get monad。谢谢你的时间!

1 个答案:

答案 0 :(得分:0)

你需要括号

return (myTrack : otherTracks)

以便不将该行解析为

(return myTrack) : otherTracks

函数应用程序比任何中缀运算符都强大。

在第一个版本中,您返回Get monad中的列表,在第二个版本中,您在do-block中有一个列表类型的表达式,其他语句是Get s。