IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

haskellでのバイナリデータの書き出し その2

バイナリデータの扱いを例として、モナドの使い方の練習を引き続き行っています。

work03$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.

# バイナリのPutモナドの作成

Prelude> let tt1 = Data.Binary.Put.putWord8 68
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package binary-0.5.1.1 ... linking ... done.
Prelude> Data.Binary.Put.runPut tt1
"D"

# バイナリのPutモナドの作成 2個目

Prelude> let tt2 = Data.Binary.Put.putWord8 69
Prelude> Data.Binary.Put.runPut tt2
"E"

# モナドの合成

Prelude> let m = tt1 >> tt2
Prelude> Data.Binary.Put.runPut m
"DE"

# ファイルハンドラの作成

Prelude> let fileH = System.IO.openFile "./test01.bin" System.IO.WriteMode
Prelude> :t fileH
fileH :: IO GHC.IO.Handle.Types.Handle

# Putモナドの中身の取り出し

Prelude> let mm = Data.Binary.Put.runPut m
Prelude> :t mm
mm :: Data.ByteString.Lazy.Internal.ByteString

# ファイルへの書き出し (なんでエラーになるの??)

Prelude> Data.ByteString.Lazy.hPut fileH mm

<interactive>:12:27:
    Couldn't match expected type `GHC.IO.Handle.Types.Handle'
                with actual type `IO GHC.IO.Handle.Types.Handle'
    In the first argument of `Data.ByteString.Lazy.hPut', namely
      `fileH'
    In the expression: Data.ByteString.Lazy.hPut fileH mm
    In an equation for `it': it = Data.ByteString.Lazy.hPut fileH mm

# do表記で書き直し。

Prelude> do {f <- fileH;Data.ByteString.Lazy.hPut f mm}
Prelude> :q
Leaving GHCi.

# 出力ファイルの確認

work03$ hexdump test01.bin
0000000 44 45                                          
0000002
work03$ perl -le 'print 16*4+4'
68
work03$ perl -le 'print 16*4+5'
69

do表記を使わずにバインドで記述したかったので、しばし悩んだ後、下記で行けました。

work03$ ghci
GHCi, version 7.6.3: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let tt1 = Data.Binary.Put.putWord8 70
Loading package array-0.4.0.1 ... linking ... done.
Loading package deepseq-1.3.0.1 ... linking ... done.
Loading package bytestring-0.10.0.2 ... linking ... done.
Loading package containers-0.5.0.0 ... linking ... done.
Loading package binary-0.5.1.1 ... linking ... done.
Prelude> let tt2 = Data.Binary.Put.putWord8 71
Prelude> let tt3 = Data.Binary.Put.putWord8 72
Prelude> let m = tt1 >> tt2 >> tt3
Prelude> let mmm = Data.Binary.Put.runPut m
Prelude> mmm
"FGH"
Prelude> let fileH = System.IO.openFile "./test02.bin" System.IO.WriteMode
Prelude> fileH >>= (\x ->Data.ByteString.Lazy.hPut x mmm)
Prelude> :q
Leaving GHCi.
work03$ hexdump test02.bin 
0000000 46 47 48                                       
0000003
work03$