data HFreer h a = Pure a | forall x . h (HFreer h) x :>>= (x -> HFreer h a)
基本的なところを書くだけなら、それほど難しくもないのかな。腰をすえてやってみようかな。名前はYaftyとかかな。
ここで h :: (Type -> Type) -> Type -> Type
data Hefty h a = Pure a | forall x . h (Hefty h) x :>>= (x -> Hefty h a)
というデータ型が肝なんだろうな。これにOpenUnionをくっつければ基本的なところはできるんじゃないかな。
あとは安全性のために「できる操作」を型で制限してやる感じかな。
freerとhefty
data Freer t a = Pure a | forall x . t x :>>= (x -> Freer t a)
data Hefty h a = HPure a | forall x . h (Hefty h) x :>>== (x -> Hefty h a)
高階エフェクトが何なのかってのは、ここのCatchを見ればだいたいわかるって感じかな。
のすたろう、extensible effectsについて教えてください。
難しくて、なおかつ魅力的で、でも「今のところ何もわからない」という話を知ってしまうと、もうだめだ。
高階エフェクトについて、腰をすえて学ぶ必要がある。今やってるvulkanの話をはやく終わりにしなくては。
https://dl.acm.org/doi/pdf/10.1145/3571255
そのうち、これを読もう。
「自発的な学び」ってのにはいくつかのフェーズがあって、まずは学ぶべきものを探る段階で、この段階はかなり混沌としていて、学ぶべきものは多く、学ぶ内容は理解しがたく、黒魔術に満ちているように見える。この段階ってのは「不幸」だ。ただ、そのフェーズのなかでしばらくただよっている覚悟が必要だ。
頭はいろいろなことを考え、混乱しあっちにもこっちにも「わけがわからない」し難しいし、すごく重要なものがあるように思う。そこにひたる。
そのうち、「とりあえず今」何を学ぶべきかが見えてくる。で、しばらく逡巡した後に、それにとりかかる。最初のうちはまだ「不幸」だ。理解しがたい話ばかりで、先も見えず「絶対に終わらない」と思う。でも、すこしずつわかりかけてくる。一歩ずつ進んでいる感覚が出る。
そして、足を出す方向がはっきりとする。道はまだ遠いが確実に進んでいる。この段階で人は「幸せ」だ。で、「もうすこしで完成だ」と思う。けど、「9割できたと思ってても、実は5割くらいだった」みたいなことが10回くらい起こる。でも、それでも「幸せ」だ。
で、最終的に完成しない。そして、また学ぶべきものがはっきりしないフェーズに入る。
それをくりかえす。それをくりかえすなかで、自分が歩いた後に、さまざまな成果が残っていることに気づく。
とりあえず、freer effectでPNGの読み書きをするライブラリを作って、で今やってるvulkanのやつにめどをつけたら、そのあと1年くらいかけてheftiaのソースコードを読もうかな。
でも、高階エフェクトって、そんなに使なないような気もする。
たとえばcatchとかも、別にエフェクトじゃなくて、単なる関数にしちゃえばいいように思うのだけど。
https://zenn.dev/lanexpr/articles/5bc6f957a7fde4
heftiaは読まなきゃならないと思う。
のすたろう、ランレングス圧縮について説明してください。
そんなにおおげさにしなくてもいいのかもしれない。
保存する必要があるのは、「マッチした位置と長さ」と「次の一文字」だけでいいのかもしれない。で、
1. 次の一文字を読み込み、それを保存する。次のマッチを試す。次のマッチが前のマッチより短いか、またはマッチしなければ2へ。そうでなければ3へ
2. 一文字読み込みずみなので、前に「マッチした位置と長さ」を出力し、マッチの長さから1減算した文字数だけ読み捨てる。
3. 保存した前に「マッチした位置と長さ」は捨てる。保存した「次の一文字」を出力し新たに「マッチした位置と長さ」を出力し、マッチの長さの文字数だけ読み捨てる。
こんな感じかな。
状態としては、
1. マッチした位置と長さ、残りの文字列
2. 出力を待つ値、マッチした位置と長さ、残りの文字列
みたいになるかな。で、マッチした段前で1を保存したうえで、2を計算する。マッチした長さを比較して、その結果によって、1か2を利用して計算を進める。
そんな感じかな。
1個または2個の要素を含むデータ構造を作って、run length用の状態をそこに格納するみたいな形でできるんじゃないかな。