型に嵌まる
Haskell初心者のお約束(「ふつける」読了程度)なんでしょうが,案の定「型に嵌まり」ました.やりたいことは
$> fib 10 55
のように,コマンドラインで引数で番号を与えると,対応するフィボナッチの項を返すというだけです.
悩んだ結果は以下の通り.
import Char import System fib :: Int -> Int fib n | n < 2 = n | otherwise = fib(n-1) + fib(n-2) strToInt :: String -> Int strToInt = foldl1 (\x y -> x * 10 + y ) . map digitToInt main = do strs <- getArgs putStr.show $ (fib.strToInt.head) strs
getArgsで取得されるのは「引数のリスト」なので,たとえ引数が一個でもそれは要素が一つのリストです.したがって,headで取り出さないと文字列にならないのです.そして,取り出した文字列が数字のみで構成されていても,それは文字列.数字ではないので,それを数字に直さないといけません.Perlならそこは勝手に処理してくれますけど,Haskellはしてくれません.
キャストの関数があるのかもしれないのですが,分からないので自前で変換するわけですが,どうも一桁の数字ならやってくれる関数digitToIntがあるとのこと.そこで取得した「数字からなら文字列」をmapでばらばらにして,それぞれの桁を変換して,「整数からなるリスト」を作ります."123"を[1,2,3]にするわけです.そのあと,(1*10+2)*10+3の計算をして123にするのですが,これはまさにfoldl1の仕事なので,それを使います.
ここまでやって,やっと引数の「数字の文字列」を整数に直して,それをフィボナッチの漸化式にいれて,結果の整数を表示させて,なんとか終了.
けど・・・やっぱり大きい番号では遅すぎます.再帰の回数が多すぎるのです.
コマンドラインで数字を受け取って,計算のタネにして,それをまた出力するという「ふつう」の作業のために苦労する・・・さすがHaskell,「簡単なことは難しく,難しいことは簡単」という評価は伊達じゃない(^^;;ただ,本質的な問題は「難しいことは簡単」というレベルに達してないということです.
コマンドラインの引数を解釈するパーサ(きっと既存のものはあるに違いないです。。PerlのGetOptみたいなもの)を考えるのも面白そうです.
追記(2007/07/09)
nobsunさん(あのnobsunさんですよね)からのコメントを頂いて
import Char import System fib :: Int -> Int fib n | n < 2 = n | otherwise = fib(n-1) + fib(n-2) main = putStr.show.fib.read.head =<< getArgs
となりました.かなりすっきりしました.ありがとうございました.こういう風にするんですね,モナドというのは.なるほど.それにしても,readは「ふつける」にもしっかり載ってました.はぅ〜.