すごいH本9

最終回!長かった…

感想
・Zipperすごい好き。
・冒頭に出てきた木、タイプ数が多すぎて絶対自分で書きたくない…と思って、7章に出てきたリストから木を作る関数を使おうとしたけど、木の構造を表すのにリストじゃ足りないか。7章でうまくいってたのは二分探索木にするっていうのと、あと元のリストが木にしたとききれいになるように並べてくれてたのね。
・穴って言うと本当に注目した点だけぽっかり空いたものを想像したけど、注目するところを根とした木全体が穴のことらしい。
・ListZipperでテキストエディタが作れるらしい。やってみようと思ったがWindowsではhSetBuffering stdin NoBufferingが効かないようでエンターを入れないと入力を取らないし、カーソルキーを受ける方法がわからない(上下に移動する操作をしたい)。HaskelineのgetInputCharを用いると入力を即受けることはできるらしいが、そもそもWindowsではエスケープシーケンスを無視する?(「On Windows, escape sequences of the form "\ESC...\STX" will be ignored.」from: https://github.comjudah/haskeline/wiki/ControlSequencesInPrompt)ので断念。
・というわけなのでWSLを入れてこちらで試す。こっちだとhSetBuffering stdin NoBufferingだけで入力を即受け取れるし、制御文字もとれた。やったぜ。
・すーっごく雑なラインエディタできた。プログラムも多分もっといい書き方あると思うけど、動かすと結構楽しい。
まずこれが型シノニムとコマンド。Zipperの第一要素に注目するのが普通だと思ったけど、(reverse snd) ++ "|" ++ fstのようにしてカーソルの左に文字を入れたり消したりするから、第二要素に注目することにした。

type StrZipper = (String,String)

goForward :: StrZipper -> StrZipper
goForward (x:xs, bs) = (xs, x:bs)
goBack :: StrZipper -> StrZipper
goBack (xs, b:bs) = (b:xs, bs)
insertCh :: Char -> StrZipper -> StrZipper
insertCh b (xs, bs) = (xs, b:bs)
backSpace :: StrZipper -> StrZipper
backSpace (xs, b:bs) = (xs, bs)

入力は前に書いたようにバッファなしで入れて、後で場合分けのためにData.Char.ordを使ってIntで返した。で、受けた入力に応じて文字列を表示させる処理をループで書いたけど…我ながらひどい。

editor (xs, bs) = do
    print $ reverse bs ++ "|" ++ xs
    input <- getKey
    case input of
        27 -> return () -- esc
        127 -> do -- bask space
            editor $ backSpace (xs, bs)
        62 -> do -- '>'
            editor $ goForward (xs, bs)
        60 -> do -- '<'
            editor $ goBack (xs, bs)
        input -> do
            --putStrLn $ show input ++ " was input."
            if (32 <= input) && (input <= 126)
                then
                    let (xs', bs') = insertCh (chr input) (xs, bs)
                    in  editor (xs', bs')
                else
                    let (xs', bs') = (xs, bs)
                    in  editor (xs', bs')

main = do
    editor ([], [])

前に悩んだ、モナドが二重になってるときどうしたらいいかわからないのがここでも。ZipperをStateでくるむとかちょっと考えたけどどうもピンとこなかった… いつまでも悩みたくなかったのでこれでいいかな、と。プログラム書き始めてから気づいたけど、本で言っているエディタは各行のリストをZipperにする意味で、これはちょっと違ってた。
・「超シンプルなファイルシステム」の木はより一般の木っぽい。これもまあまあタイプ数が多いから試す気にならなかった。
・「木構造の境界に気(木)をつけて…」ってギャグは英語でどういう風に書くのかと原文を見たら「… if we don't keep within the bounds of our tree」でちょっとわからなかった。それはそうとkeepも「木ーぷ」になる。

去年の8/19から実に6か月以上。非常に時間がかかったけどこれで無事、すごいH本を読み終わった。おつカラーズ☆