Exercise 9.9

fix 関数の型はどんなものかってのと、 fix を使って remainder を再帰でない形に書き直しなさいって問題。 fix と remainder の定義はそれぞれ以下のとおり:

fix f = f (fix f)

remainder :: Integer -> Integer -> Integer
remainder a b = if a < b then a
                else remainder (a - b) b

こういう問題をみると、おら、わくわくしてくっぞ!

で、 fix についてうんうん考えて、右辺から f は最低でも 1 引数をとれないとダメだってことから (a->b) -> b って型を考えてみた…んだけれど、 GHCi 先生にお尋ねしたら間違いだったことがわかりました無念。

Prelude> let fix f = f (fix f)
Prelude> :t fix
fix :: (t -> t) -> t

なるほど、再帰式だから型がそろってないとダメなんだ。再帰でない形に remainder を書き直すほうは、これもうんうんうなって考えた。答えはきっとこれでいい:

remainder a b = fix (\ f a -> if a < b then a else f (a - b)) a

-- anonymous function のところの問題なんだから次のように定義した
-- ほうが、よりよい…のかもしれない。
-- remainder = \ a b -> fix (\ f a -> if a < b then a else f (a - b)) a

これって計算機プログラムの構造と解釈 (SICP) の 4 章にあった Y Combinator の話だよなきっと。