blog.bouzuya.net

2018-06-09 Halogen の Component を String にできない話の続き

bouzuya/tamaru 。些細な点にこだわりすぎて進んでいない。

昨日 (2018-06-08) の子 Component の描画に対応しようとしていた。結論から書くと、ぼくにはまだできなかった。 RenderSpec を雑に実装している点と slamdata/purescript-halogen-vdom-string-renderer を組み合わせている点がまずそうだ。

どこで詰まっているのかを整理するため、ぼくの現状の実装について書く。

ソースコードは https://github.com/bouzuya/tamaru/blob/9e258b97640d978e76fcd9570fa5a03f3474c0a0/src/Server/ComponentRenderer.purs

halogen は通常 Halogen.VDom.DriverrunUI を使用して動かす。これは実 DOM (DOM.HTML.Types.HTMLElement) に対して指定した Component を描画し、動かしていく。この runUI は内部で Halogen.Aff.DriverrunUI を使用している。こちらの runUI へ実 DOM に依存していないので、ぼくはこれを使っている。

ぼくの現在の実装は、この Halogen.Aff.DriverrunUI へ実 DOM に依存しない適当な RenderSpec を与えることで文字列として描画しようとしている。この RenderSpec の組み立て方がよく分からないのだけど、大切なのは render くらい。……くらいと書いたが、↓みたいな型になっていて、ぼくみたいのには「よく分からない」以上の感想が出てこない。

render
  :: forall s f g p o
   . (forall x. InputF x (f x) -> Eff (HalogenEffects eff) Unit)
  -> (ComponentSlot h g (Aff (HalogenEffects eff)) p (f Unit) -> Eff (HalogenEffects eff) (RenderStateX r eff))
  -> h (ComponentSlot h g (Aff (HalogenEffects eff)) p (f Unit)) (f Unit)
  -> Maybe (r s f g p o eff)
  -> Eff (HalogenEffects eff) (r s f g p o eff)

これを雑に説明すると↓のとおりだ。

  • Component への Query を処理するハンドラー
  • 子要素を描画するハンドラー
  • 要素
  • 前の RenderState

Halogen.VDom.DriverrunUI では、これを halogen-vdom でつくれる「実 DOM を更新していく machine 」や描画結果の実 DOM を返す RenderState で実装している。

ぼくはまともに machine や RenderState を用意していない。最初に渡される要素を Halogen.VDom.DOM.StringRendererrender に与えていた。

ここまでが現状の実装。で、何が問題なのか。

Halogen.VDom.DOM.StringRendererrender は↓のような型だ。

render ∷ ∀ i w. (w → String) → VDom (Array (Prop i)) w → String

w というのが halogen-vdom の Widget だ。ぼくはこれがほとんど使われないものかと思っていたので const "" という適当な値にしていた。しかし、実際には halogen の子 ComponentComponentSlot を使用しており、それはすべて Widget なのだった。

たぶん、まともに machine を実装し Halogen.VDom.DOM.StringRenderer を捨てるか、強引に ComponentSlot をバラして render する関数 (w -> String) を実装すればなんとかなると思う。どちらも地獄っぽい。


今日も出かけた。わけあって暑い時間帯に出かけることとなった。暑すぎて、ひどく汗をかいたし、疲れた。

2018-05-31 にも書いたけど、この数週間で土日に出かける頻度が増えており、思ったように進まない。↑も断片的に調べるせいで、何がなんだか分からなくなっている。

おまけに明日も出かけるんだよな……。