自然数の無限リストはInt?それともInteger?(別解説)
と、id:kazu-yamamotoさんの記事に書いていたようだったのでhaskell使用歴10日程度の僕は興味を持って調べてみることにしました。というのが背景です。ポリシーとしては基本仕様から調べるということで。
自然数の無限リストはInt?それともInteger?
とりあえず、[1..]ってのがhaskellではどう定義されているかを見てみませう。
http://haskell.org/onlinereport/exps.html#arithmetic-sequences ←こんな感じ。
[0..]や、[0..10]に代表されるリスト内包表記(list comprehensions)はhaskellの糖衣構文なのですね。つまり、[1..]と書くとそれは(enumFrom 1)といった式に内部で変換されてから、処理が行なわれるのです。ならばenumFromの型を見れば[1..]の型が判明するのです!! をぉ。簡単! ということで、Hugsでお試し。
Hugs> :t enumFrom enumFrom :: Enum a => a -> [a]
えーと。なんですか? 型クラス(Enum a)において、aを受けとってaのリストを返す関数ですか。つまりenumFromは型クラス(Enum a)をサポートしていれば使えると。んじゃ、Enum aを継承しているDoubleとかでもできるの?!
…試してみた (トリビアの泉風に)。
#Hugs ver. Sep 2006 Type :? for help Hugs> [0.22..2.33] [0.22,1.22,2.22] Hugs> [0.22..2.22] [0.22,1.22,2.22]
# GHCi 6.8.2 Prelude> [0.22..2.22] [0.22,1.22,2.2199999999999998] Prelude> [0.22..2.23] [0.22,1.22,2.2199999999999998]
をぉ。できるやん。GHCiは返り値がなんとなく微妙だけれど。まぁ、型的に納得できる。納得できるけれどさぁ…俺の求めている答はどこにあるのさぁ!!
(ここで少しの苦悩と逡巡があった)
…で結局はそうなると「"10"とhaskellって書いたとき、それは何の型を持つの?」という問題になる訳ですね。10って数字はIntかもしれないし、Integerかもしれないし、Doubleかもしれないのです。言語の評価機としては与えられた数値に対して、なにかしらの型を与えて処理をしないといけない訳です。特に型推論とか持っているhaskellならばなおさら。で、その規約もhaskellの言語仕様にはありました! さすが言語仕様書。
「貴様らの歩んでいる道は、我々がすでに通った道 だ!(from グラップラーバキ)」 と言われんばかりですね。
http://haskell.org/onlinereport/decls.html#default-decls ←ここ
ということで、ここを見るとモジュール内でdefault(型1, 型2)と宣言した順番にマッチさせようとすることになっています。何も指定しない場合(つまりdefaultのdefault)は"default (Integer, Double)"になっているとのこと。よって、
- [1..]と打つとenumFrom 1として計算される。型はEnum a => a -> [a]
- 特にdefault()で指定しない場合haskellは"1"をIntegerの"1"として認識する
- つまりenumFrom 1の型は Integer -> [Integer] になる
結果、無限リストになる訳ですね。
んじゃ、こんなファイルを作って、Hugsでテストしてみましょう。
module Test where default (Int, Double) k = let a=[2..] in a
Hugs> :load hogefuga.hs Test> :t k k :: [Int]
をぉ。Intになったね。という話ですた(オチなし)。