0

我正在尝试阅读 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. 想要将此技术应用于其他二进制文件,其中包含“某些东西”的列表。

当我尝试编译它时,我得到了这个错误:

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当我被迫使用这样的列表连接时,我不知道如何制作单子。谢谢你的时间!

4

1 回答 1

0

你需要括号

return (myTrack : otherTracks)

为了使该行不被解析为

(return myTrack) : otherTracks

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

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

于 2013-03-14T14:32:28.597 回答