これは、ひとり Advent Calendar 2016 7日目の記事です。
前回は、以下の2つに取り組む必要があると書きましたが、その続き。
まず、前者については、勘違いしていました。IO 向けに特殊化された (specialized) >> は、 もう特殊化されているので、もはや多相関数ではありません。なので、これを単相扱いにしていたこと自体は正しいのでした。 つまり、これはたまたま動いていたのではなく、意図的にこのように実装したのを、すっかり忘れていただけでした。
ただ、ここでも微妙なところはあって、p >> q = p >>= \_ -> q というように、>> のなかで >>= を呼んでいるのですが、これを IO に特殊化された >>= だと決めつけているところは、 難があるというか、まちがっていると思う。多相関数の specialization は、やるなら、もっときちんとやるべき。
ま、とりあえずは、このままでいきます。
というわけで、後者。辞書を受け取って、それを、他の多相関数に渡すような多相関数の扱いをやりました。
まず、こういった関数が、いくつの辞書を、どの順で受け取るのかについては、その関数の Qual Type における [Pred] を見ればわかります。
[Pred] が空の場合は、単相関数なので、これまで通りの処理で OK。
[Pred] が空でない場合は、この [Pred] の要素数と同じだけの dictionary 変数を引数に取るので、 これを受け取るような Lambda 式で全体をくるんでやって、この Lambda の仮引数を適切に使うように dictionary-passing style 変換してやればよかった。 (いまの私自身にしか通じなさそう*1な説明ですが)
あ、そうだ、↑これで動いてはいるんだけど、辞書を束縛する変数に TermVar を流用しているのは、いまいちかも。 ToDo に書いておこう。
ともあれ、以下のサンプルが動くようになりました。
f x y = x > y s True = "True" s False = "False" main = do putStrLn $ s (f 100 10) putStrLn $ s (f 'x' 'y')
実行結果:
$ ./run test8d/Sample.java True False
あとは、tcExpr が網羅的でないのを、ちょびちょび補充していけば、完成に近づくんですかね。
それはそうと、DictPass というファイル名、あんまりイケてないなぁと思っていたんだけど、 タコっぽくてかわいいような気が、今日急にしてきました。