Haskell でライフゲーム(Wikipedia が分かりやすい)を作った。一番悩んだのが、プログラム本体よりもIOモナドで無限ループをどう記述するかだった。
Control.Monad モジュールにはアクションの繰り返しをコントロールできる関数がいっぱいあるが、cs <- display cs の繰り返しを作ろうとしても、これは完全なアクションではないのでうまくいかない。結局セル平面の状態の無限リストを作り、それを頭から表示していく末尾再帰型の関数を作ってみたが、スタックがオーバーフローするかもしれない。 やはり、IOモナドは一筋縄ではいかない。ライフゲームのようなプログラムは手続き型のほうが楽だ。 逆に、本体のほうは生のインデックス(i や j のInt型)を極力使わないで記述することができた。構造のあるデータを抽象化して扱うことができるのは Haskell のありがたい点だ。簡潔な記述や可読性はこの抽象データの扱いやすさによるものだ。 抽象的なデータの力は、ここでは使わなかったが、Haskell の algebraic data を作ってみるとよく分かる。 どのプログラム言語が一番かというのではなくて、それぞれのプログラム言語の得手不得手がある。将来的にはそれらを融合した、もっと簡潔でパワフルな言語が生まれてくるかもしれない。プログラム言語の進化の余地があるというのは楽しみなことだ。 プログラム名:lifeGame.hs import System.Cmd import Data.Array top, bottom, wtop, wbottom :: (Int,Int) top = (0,0) bottom = (11,11) wtop = (1,1) wbottom = (10,10) main = stage (game cell) stage (x:xs) = do display x stage xs return () display c = do system "clear" putStr (showCell c) getLine return () game cs = cs : game (step cs) step :: Array (Int,Int) Int -> Array (Int,Int) Int step cell = array (top,bottom) newcell where newcell = [(x,0)| x <- range (top,(fst top, snd bottom))] ++ [(x,0)| x <- range ((fst wtop, snd top),(fst wbottom, snd top))] ++ [(x,0)| x <- range ((fst wtop, snd bottom),(fst wbottom, snd bottom))] ++ [(x,0)| x <- range ((fst bottom, snd top),bottom)] ++ [(x,alive x)| x <- range (wtop, wbottom)] area x = range ((fst x - 1, snd x - 1),(fst x + 1, snd x + 1)) crowd x = sum (map (cell !) (area x)) alive x | cell ! x == 0 && crowd x == 3 = 1 | cell ! x == 1 && crowd x == 3 = 1 | cell ! x == 1 && crowd x == 4 = 1 | otherwise = 0 showCell :: Array (Int,Int) Int -> String showCell cell = concat [concat [ show (cell ! x) | x <- range ((i, snd wtop), (i, snd wbottom))] ++ "\n" | i <- range (fst wtop, fst wbottom)] cell :: Array (Int,Int) Int cell = array (top,bottom) init where init = zip (range ((0,0),(0,11))) [0,0,0,0,0,0,0,0,0,0,0,0] ++ zip (range ((1,0),(1,11))) [0,0,1,0,0,0,0,0,0,0,0,0] ++ zip (range ((2,0),(2,11))) [0,0,1,0,0,0,0,0,0,0,0,0] ++ zip (range ((3,0),(3,11))) [0,0,1,0,0,0,0,0,0,0,0,0] ++ zip (range ((4,0),(4,11))) [0,0,0,0,0,0,0,0,0,1,0,0] ++ zip (range ((5,0),(5,11))) [0,0,0,0,0,0,0,0,1,0,0,0] ++ zip (range ((6,0),(6,11))) [0,0,0,0,0,0,0,0,1,1,1,0] ++ zip (range ((7,0),(7,11))) [0,0,0,0,0,0,0,0,0,0,0,0] ++ zip (range ((8,0),(8,11))) [0,0,0,0,0,0,0,0,0,0,0,0] ++ zip (range ((9,0),(9,11))) [0,0,0,0,0,0,0,0,0,0,0,0] ++ zip (range ((10,0),(10,11))) [0,0,0,0,0,0,0,0,0,0,0,0] ++ zip (range ((11,0),(11,11))) [0,0,0,0,0,0,0,0,0,0,0,0] 実行例:リターンキーを押すと次の画面が表示される。中断は、Ctr + C で。 Hugs> :l lifeGame.hs Main> main 0100000000 0100000000 0100000000 0000000010 0000000100 0000000111 0000000000 0000000000 0000000000 0000000000
by tnomura9
| 2009-11-03 11:27
| Haskell
|
Comments(0)
|
カテゴリ
新型コロナウイルス 主インデックス Haskell 記事リスト 圏論記事リスト 考えるということのリスト 考えるということ ラッセルのパラドックス Haskell Prelude Ocaml ボーカロイド 圏論 jQuery デモ HTML Python ツールボックス XAMPP Ruby ubuntu WordPress 脳の話 話のネタ リンク 幸福論 キリスト教 心の話 メモ 電子カルテ Dojo JavaScript C# NetWalker ed と sed HTML Raspberry Pi C 言語 命題論理 以前の記事
最新のトラックバック
最新のコメント
ファン
記事ランキング
ブログジャンル
画像一覧
|
ファン申請 |
||