バイナリ ファイルを扱うための教育的演習として 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 つあります。
- 最後に無視したいゴミがあるかもしれません。
- 内部に「何か」のリストがある他のバイナリ ファイルにこの手法を適用したいと考えています。
コンパイルしようとすると、次のエラーが発生します。
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
このようにリスト連結を使わざるを得ない状況でモナドを作る方法がわかりません。御時間ありがとうございます!