PDFリーダーの日本語モード対応と同人誌

日本語モードについて

ご無沙汰しています。日本語モードを作り始めたらそれなりのものができてしまったので、さっさと公開することにしました。
GitHub(Ubuntu, Windows)に投稿していますので、詳しくはそちらを参照ください。mecab云々が書かれている箇所です。
Windows版への移植も適当にやったらやれてしまいました。
Mecabのエンコード周りが鬼門だと思っていたのですが、UTF8とchcp 65001に注意すれば問題なしでした。

同人誌について

技術書典9が、9/12(土) 10:00 ~ 9/22(祝)23:59でオンラインで開催されるようです。
前回はコロナの影響で当初予定されたリアルイベントではなく、結果的にオンライン上で応援祭の形式をとっていました(運営さん大変そうでしたね、、)が、今回は公式にオンラインのみのようです。
頒布される同人誌には電子版(おそらくPDF)形式を用意するのが必須、という条件っぽいので、これに乗じて自分もこのPDFリーダーネタで同人誌書こうという計画でいます(審査、通らなかったら残念ですが、どちらにせよ良い機会なので本の形にする予定です)。
以下の4つを中心に書こうと計画しています。
タイトル (同人誌を自作PDFリーダーで読もう – Haskellでつくる関数型玩具(仮))

  1. 色を付けて読むことのポテンシャル
  2. 実際に色をつけて読む際の戦略
  3. Haskellでプログラム修正すると面白いよ
  4. 高度な数学の応用の可能性(発展的話題)

タイトルの自作PDFリーダーの下りは多分変えます。今回はGUIを作るパートは含めないからです(あと1ヶ月だと内容絞らないと間に合わないかなと。プログラムも現状汚いですし、、)。
その中でも、純粋関数でいじると面白そうな箇所(上記3.)についてフォーカスして、今回は予告編的に終わっておくつもりです。

色を付けて読むことのポテンシャル

これは、このHPでは何度か出てきてるので割愛です。

実際に色をつけて読む際の戦略

実際に読む際の戦略についてはまだあまり記事にもしていないです。
このあたり、うまくやらないと目がチカチカするのみで逆効果になってきます。
今は説明も何もせずユーザーの人にいろいろ遊んでくださいのスタンスですが、
この箇所で書く予定の戦略を用いればだいぶ読みやすくなるというのが、自分の実感です。

Haskellでプログラム修正すると面白いよ

プログラム修正する箇所は日本語文のparserのところです。
ファイル的にはfromPDF.hsのfoldNPsJPRecursiveという関数、およびそこで使われている小さい関数の組み合わせ、
となってきます。これは、ここ数日で自分がカスタムチューニングしたものになりますが、まだまだ改善の余地がありますし、
人によっては色を付ける単位として自然なものは異なってくるかと思います。これをネタに自分でHaskellを使ってチューニングする、
その取っ掛かりを記事にする予定です。極力、Preludeにのっているmap, fold, filterなどの定番の高階関数とラムダのみでやっていきますので、
実践を通してHaskellの基本が学べる予定です。
これをきっかけにHaskellerが増えてくれると面白いかなと。
関数を適用した結果はREPLでみたり、特定の本で着色してみたりして確認していきます。
この2週間位、自分もそのやり方でチューニングしていきましたが、だんだん思った感じで構造が作れると楽しくなってきます。
他人の作ったライブラリではなく、自分で考えたアルゴリズムはかけがえのないものです。
本当はMecab的なものについても自分で作れるとよいのですが、ちょっとむずかしそうなのでパスですね、今は。
すでにHaskellerの方はparsecとか、megaparsecとか、いかにもHaskellっぽいparserでこのfoldNPsJPRecursiveを書き換えるのがいいと思います。
後述のS式の型を合わせておけばいいだけです(★1)。

高度な数学の応用の可能性(発展的話題)

実は、最初は以下に話すやり方で日本語モードを実装しようとしていたのですが、
結局人間(私)の目から見て、自然な単位になる文法規則的なものを手でチューニングしたのが現在の日本語モードです。
手でやらなくても、以下の通りにやれば勝手に名詞句が抽出できる、予感がしています。
まず前提として名詞句は入れ子構造になっています。例としては、

[[[いかにも[[Haskell]っぽいparser]]で[[この[foldNPsJPRecursive]]を書き換えるの]]がいい]と思います

といった感じです。[]で囲われた箇所が名詞句です。
この例のようにNestしたリストで文章を表現するのもありですが、poppySではS式を採用しました。

data SExp a b where
  Nil :: SExp a b
  Atom :: a -> b -> SExp a b
  Opr :: a -> [SExp a b] -> SExp a b

AtomとしてプリミティブなTag付きのtoken, OprとしてTagとその下にぶら下がっている他の要素いった感じです。
このTagに名詞句やその他品詞といった情報が乗ってきます。
名詞句って何かというと、「それ」(指示代名詞)で置き換え可能な単位と私は定義しています。世の中的にも多分そうです。
そして、「それ」で置き換えたとしても、周りは文法的には何も関係性が変わらない、というのが重要と見ました。
これは、なにか関数があって置き換えた前と置き換えたあとで、「その関数の適用前後」として変わらないという抽象化ができます。
これって結構大事なことかと思っています。今回のであれば、Mecabの関数(IOつきですが、getMecabedというのを作っています)に入れた際に、
支持代名詞に置換前と置換語で周りの品詞とかの関係性が変わっていない、というものになりますが、
日常生活の中でも、例えば文脈によっては性別のみが問題になる(例としてレディースデーの対象。そこに花子さんとか愛子さんとか個々の人間性は問題にしない、女性なら誰でも良い)、
年齢のみが問題になる(例としてシルバーデー)、
などといった具合です。ちょっと長くなりそうなのと、同人誌のネタにしたいのでこの辺にしておきます。
ただ、Mecab周りの関数がレディースデーの場合は例えばレディースデー用のチケットを買って店員さんに見せた場合にどうなるかという判定に相当します。
状況変わらないかというと、 怒られて通常料金払えということになりますが、そういう強硬手段でなくても男性か女性かというのは判別可能なはずです(他の関数がありそうです)。
ジェンダーの問題とかありますが、ここではそういう差別的で話していないとご理解ください。逆に言うと男性女性といっても文脈によっていろいろなリトマス試験紙があるにもかかわらず、
一つのリトマス試験紙で他のすべての判別をしようとする、そこにジェンダー的な問題があるのだとも見えます。
適当に思うままに書いていますが、名詞句、ジェンダー、こういう一見同じに見えない類のネタがつながって見えるのが数学のいいところだと思っています。
ふんわりとしていますが、そのあたりの妙味も同人誌で表現できたらな、といった感じで記事を閉めます。

(★1)
foldNPsJPRecursive以外の、清書していない箇所(特にmain.hs)については触れずにやり過ごす予定です(笑)
ガチなHaskeller諸氏は見てはいけません(笑)。
readIORef, modifyIORefをゴリゴリ書くのはなんかしんどかったです。
ただし、こうやってIOまみれで書けばHaskellでもGUIやれるという証拠にはなっているのかなと思います。
lensとか使えばきれいにかけるんですかね。
一応自己弁護としては教育の題材に使う予定なので、Preludeにない特殊記法は避けようというモチベーションでlensは使いませんでした(正確には勉強して導入すること、はしませんでした。)

シェアする

  • このエントリーをはてなブックマークに追加

フォローする