haskellのlookAheadの練習
BinaryパッケージにlookAhead関数があります。
https://hackage.haskell.org/package/binary-0.5.0.2/docs/src/Data-Binary-Get.html#lookAhead
Prelude> :t Data.Binary.Get.lookAhead Data.Binary.Get.lookAhead :: Data.Binary.Get.Get a -> Data.Binary.Get.Get a
型をみると、GetモナドをとりGetモナドを返す関数で、使い方がイメージできませんでした。
ソースを確認すると、getしてputするという地道な(!)ことをしています。
-- | Run @ga@, but return without consuming its input. -- Fails if @ga@ fails. lookAhead :: Get a -> Get a lookAhead ga = do s <- get a <- ga put s return a
これをみるとgaという関数を実行しているので、lookAhead関数に関数を渡せば良いことがわかります。
なので、lookAhead関数にGetモナドを渡せばよいと。
Prelude> Prelude> :t Data.Binary.Get.lookAhead Data.Binary.Get.getWord8 Data.Binary.Get.lookAhead Data.Binary.Get.getWord8 :: Data.Binary.Get.Get GHC.Word.Word8 Prelude>
準備としてByteStringの作成
Prelude> :t Data.ByteString.Lazy.Char8.pack Data.ByteString.Lazy.Char8.pack :: [Char] -> Data.ByteString.Lazy.Internal.ByteString Prelude> Data.ByteString.Lazy.Char8.pack "123acdefg" "123acdefg" Prelude>
1バイト目を取得
Prelude> Data.Binary.Get.runGet (Data.Binary.Get.getWord8) (Data.ByteString.Lazy.Char8.pack "123acdefg") 49 Prelude>
1バイト目を先読みで取得
Prelude> Data.Binary.Get.runGet (Data.Binary.Get.lookAhead Data.Binary.Get.getWord8) (Data.ByteString.Lazy.Char8.pack "123acdefg") 49 Prelude>
1バイト分だと先読みしているかがわかりにくいので、バイト読み込みを2回してみます。
2バイト目を取得
Prelude> Data.Binary.Get.runGet (Data.Binary.Get.getWord8 >> Data.Binary.Get.getWord8) (Data.ByteString.Lazy.Char8.pack "123acdefg") 50 Prelude>
1バイト目を先読みして、もう一度1バイト分を読む
Prelude> Data.Binary.Get.runGet (Data.Binary.Get.lookAhead Data.Binary.Get.getWord8 >> Data.Binary.Get.getWord8) (Data.ByteString.Lazy.Char8.pack "123acdefg") 49 Prelude>
確かに先読みしていることが確認できました。