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ヘッダー ファイルで宣言されているトラック数です。このようにしたい理由は 2 つあります。

  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

関数適用は、どの中置演算子よりも強力にバインドします。

最初のバージョンでは、モナドでリストを返しますGet。2 番目のバージョンでは、他のステートメントがGets である do ブロックにリスト型の式があります。

于 2013-03-14T14:32:28.597 に答える