fix関数に適用したら無限ループになる理由
前提
不動点コンビネータである
fix関数は、引数に取った関数
f
の最小不動点を返す
関数 f
の不動点とは、 f x == x
を満たす x
のことである
この等式を満たす x
は複数存在することもある
fix
はその内の最小なものを返す
以下の疑問に答える
関数 f = (*3)
を fix
に適用した時に、なぜ 0
じゃなくて無限ループになるのか?
ghci(hs)> f = (*3) -- f :: Int -> Int
> fix f -- 無限ループ!
「最小」と言うのだから、 0 * 3 == 0
なんだし 0
が返ってくるべきでは?と思ったりする
「最小」とは言うが、何の順序の話をしているのかを捉え違えるとこう誤解する

その順序が Int
の数値の大小関係\leの話ならば確かに 0
かもしれない
しかし、ここでの順序はそれではない
結論
最小不動点は、この順序における最小なものを返す
それが f = (*3)
の場合は、 undefined
なので無限ループになる
以下のことを抑えておく必要がある
未定義
無限ループ
例えば、以下の関数を考える
これは、引数に何を取っても "x"
を返す関数
hsf 1 -- "x"
f True -- "x"
f "x" -- "x"
..
この f
の不動点は唯一つであり、それは "x"
従って、最小不動点は "x"
である
実際、 fix f
の返り値は "x"
になる
これは不動点の例として直観に沿う簡単な例

例えば、以下の関数を考える
これには複数の不動点が存在する
例えば、 0
∵ 0 * 3 == 0
例えば、 undefined
∵ undefined * 3 == undefined
この時、どちらがより小さいか?が問題になる
以下2点を抑える必要がある
どういう集合を考えているのか?
ここで考えている集合は、Haskellの型 Int
である
つまり、 Int = {...,-1,0,1,...} ∪ {undefiend}
である
どういう順序を考えているのか?
この2点を踏まえると
Int
の
意味近似順序を表したハッセ図式は以下のようになる
任意の整数nに対して、\mathrm{undefined} \sqsubset nだし、
0
や 1
の間には順序は定義されていない
ここで、元の f
の不動点は 0
と undefined
があった
この時、順序関係は\mathrm{undefined} \sqsubset 0である
故に、最小不動点は undefined
実際、 fix f
の返り値は、無限ループになる
結論
不動点が複数あり、その中に\botを含む場合は fix
によって\botが得られる
この\botには、未定義や無限ループが含まれる