Scalaz に Monoidal を実装してみた

まだ10日だけど、これを Scalaz_Advent 2012 の 11日目 にしてしまっていいんじゃなイカ?


typeclassopediaの日本語訳 ではなく、 Haskell wiki にある英語のほう


http://www.haskell.org/haskellwiki/Typeclassopedia


を読んでいたら、日本語訳したのはもう3年も前なわけで、色々と日本語訳には書いてないことが追記されてた。( そのあたりの事情? )

そこに、Monoidal というのがあって(日本語訳のほうにはない)


http://www.haskell.org/haskellwiki/Typeclassopedia#Alternative_formulation


一言で言うと「Applicativeと同じものを別の形でも表せる」ということらしい(?)

Applicativeがこういう定義なのに対して

class Functor f => Applicative f where
  pure  :: a -> f a
  (<*>) :: f (a -> b) -> f a -> f b

Monoidalはこう

class Functor f => Monoidal f where
  unit :: f ()
  (**) :: f a -> f b -> f (a,b)

「違う形で表した場合に、実用上どのように便利なのか?」とかは知らない。というわけで(?) Scalaz にとりあえず組み込んでみたのが以下


https://github.com/scalaz/scalaz/compare/scalaz:b592c73...xuwei-k:3f42268


ApplicativeとMonoidalが同じものということは、つまり

ということだと解釈したので、
「Applicaitveのtraitから、monoidalというメソッドを呼ぶと、Monoidalのインスタンスが取得できるように」定義してみたら、できた。逆も同じ。


ちなみに、まったくテストしてないので、実は循環参照して無限ループになってるとか、もっとシンプルに定義できるのに無駄な努力してる部分とかあるかもしれない。


そして、MonoidalのLawについても書いてあったので

http://blog.ezyang.com/2012/08/applicative-functors/

実装しようとしてみたけれど、 の記号の意味(イコールだと捉えて実装しても型が合わない。同型という意味?だとしたら、どうやって実装すれば?)とか、以下の文の意味がイマイチ完全に理解できなくて

I’ve prettied things up a bit by using “is isomorphic to” in order to suppress the differences between ( (), a) and a, as well as (a,(b,c) ) and ( (a,b),c), for strict equalities you’ll need some extra functions to massage the results into the right types. It seems that there is a general pattern where the API which has nice formulations of laws is not convenient to program with, and the formulation which is nice to program with does not have nice laws. C’est la vie... but at least they’re equivalent!

途中で諦めた(´・ω・`)

誰か詳しい人*1の解説求む・・・。
もちろんこれをScalaz本体にpull requestしようとかは思ってません、単にやってみただけです。*2



追記:

*1: lawの部分に限らず全体的に理論的な背景とか

*2: 実は、実用に役立つなら入って欲しいですが、普通に考えて役立ちそうにない