HGL
今が旬の赤紫蘇を使って、紫蘇ジュースを造ってみた。作り方は、Googleおばさんに聞いて ください。いろいろあって、微妙に違っていたりして、面白いです。
熱湯に、紫蘇の葉を入れて暫くすると、葉の色素が湯に溶け出して、葉が緑色になる。抽出液 に、酢を加えると、赤黒かった液がruby色になるのが、理科の実験みたいで面白かったです。 砂糖の量を控えておくと、焼酎割りにも最適! rubistは、ルビー色に輝く飲み物を補給 しながら、Hackにいそしんでください。
Haskellの配列
rubyのサンプルをHaskellに置き換えようとすると、どうしてもHaskell上で使える配列が欲しくなる。 どうやって使うんだろうと思って、調べてみた。
import Array lang = listArray(1,4) ["haskell", "Scheme", "Ruby", "C#"] best = lang ! 1 best' = lang // [(4, "Clojure")] *Main> :load "c:/sakae/HS/ar.hs" [1 of 1] Compiling Main ( C:\sakae\HS\ar.hs, interpreted ) Ok, modules loaded: Main. *Main> lang array (1,4) [(1,"haskell"),(2,"Scheme"),(3,"Ruby"),(4,"C#")] *Main> best "haskell" *Main> best' array (1,4) [(1,"haskell"),(2,"Scheme"),(3,"Ruby"),(4,"Clojure")]
2行目で、配列を定義し、3行目で、アクセス、最後の行で書き換え。更新は出来ないのが 微妙(何、この仕様はROMですか) 更に痛いのは、定義したサイズを埋めないと、エラーに なってしまう事。
これじゃ、普通にイメージしてる配列とは大違いだ。Data.Array.IOとかを使うと、普通の配列と 同様な操作が出来るらしいけど、IOがネックかな。Hashを使った方が自由度が高そう。
実用サンプルはどうしてるの?
向井さんの 「入門Haskell」をぱらぱらと、めくってみた。そしたら、 samegameの例が出てきて。。。 List構造になってましたね。やっぱり基本ですよね。切り貼り も簡単だし、豊富に関数が揃ってますから。
でも、Listは、順番にアクセスする必要があるのは、テープと一緒。ランダムアクセスが出来ない のが痛い。嗚呼、テープの切り貼りって昔、よくやりましたよ。1インチ幅の紙テープを使って いた頃、たまにパンチミスをすると、もったいないので、その部分を切り取って、新しいテープで 置き換えてしまう。これが、本当のPatchです。
更に、ソースプログラムのdiffは、、、 薄いLP用紙に印刷して、それを新旧2枚重ねて、 Sun に透かしてみる。違いが一発で検出できます。なんて言う昔話をしてるんだよう。
HGL
この向井本の例を見ていくと、samegameをGraphicsにしましょう、となってHGLが紹介されて いる。FreeBSDにHGLを入れてみた。(libgmpが新しいのを要求され、古いのを消したらghcが 動かなくなった。慌てて、新しいlibraryからリンクを貼ってごまかしてしまったのは、秘密だ)
ぐぐったら、HGLのサンプルを何方かが紹介されてたので、忘れないように貼っておく。
module Main where import Graphics.HGL -- スクリーン情報 width::Int width = 320 height::Int height = 240 widthF::Float widthF = 320.0 heightF::Float heightF = 240.0 -- ボールオブジェクト data BallObj = BallObj { x, y :: Float, dx, dy :: Float } -- ボールから座標を取得 toPos::BallObj -> Point toPos ball = (round $ x ball, round $ y ball) -- 色定義 color = RGB 255 255 0 -- 描画関数を返す drawball:: Point -> Graphic drawball (x,y) = do withRGB color $ ellipse (x-10, y-10) (x+10, y+10) -- 描画 draw::[BallObj] -> Graphic draw balls = do mapM_ drawball $ map toPos balls -- 移動 moveBall:: BallObj -> BallObj moveBall ball = BallObj { x = (x ball) + (dx ball), y = (y ball) + (dy ball), dx = (dx ball), dy = (dy ball) } -- 状態の更新 updateState::[BallObj] -> [BallObj] updateState balls = (map boundBall (map moveBall balls)) -- 初速 speed0 = 0.5 -- ボール達 balls= [ BallObj{dx= speed0*4, dy= speed0, x=0, y=0}, BallObj{dx= -speed0, dy= speed0*4, x=widthF, y=0}, BallObj{dx= -speed0*2, dy= -speed0*3, x=widthF, y=heightF}, BallObj{dx= speed0*3, dy= -speed0*2, x=0, y=heightF} ] -- 跳ね返り boundBall::BallObj -> BallObj boundBall ball = let px = x ball py = y ball vx = if px < -3 || px > widthF+3 then -(dx ball) -- 反転 else dx ball vy = if py < -3 || py > heightF+3 then -(dy ball) -- 反転 else dy ball in BallObj { x = px, y = py, dx = vx, dy = vy } -- ゲームループ -- ウィドウ -> ボールオブジェクト loopGame::Window -> [BallObj] -> IO() loopGame w balls = do e <- maybeGetWindowEvent w -- イベント処理 case e of Just(Char {char=c}) -> -- ESCキー if c == '\ESC' then closeWindow w else loopGame w balls Nothing -> do -- 描画処理 setGraphic w $ do draw balls getWindowTick w loopGame w (updateState balls) _ -> loopGame w balls -- エントリポイント main::IO() main = runGraphics $ do w <- openWindowEx "test" Nothing (width, height) DoubleBuffered (Just 3) -- ループ開始 loopGame w balls
Windows では?
HGLはWindows上でも動くとの事なので、試してみた。
c:\>cabal.exe install HGL Warning: The package list for 'hackage.haskell.org' is 16 days old. Run 'cabal update' to get the latest list of available packages. Resolving dependencies... Downloading HGL-3.2.0.0... Configuring HGL-3.2.0.0... Preprocessing library HGL-3.2.0.0... Building HGL-3.2.0.0... Graphics\HGL\Key.hs:57:7: Could not find module `Graphics.Win32': it is a member of the hidden package `Win32-2.2.0.0' Use -v to see a list of the files searched for. cabal.exe: Error: some packages failed to install: HGL-3.2.0.0 failed during the building phase. The exception was: exit: ExitFailure 1
見事に失敗してます。ググってみたら、やはり世界中に悲しい思いをしてる人が いました。解決方法は提示されていません。
そこで、チャレンジしてみました。ghciなら、よく見えると思ったのでした。
c:\sakae\HGL-3.2.0.0>ghci GHCi, version 6.10.3: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer ... linking ... done. Loading package base ... linking ... done. Prelude> :load Setup.hs Ok, modules loaded: Main. Prelude Main> :main build Loading package syb ... linking ... done. Loading package array-0.2.0.0 ... linking ... done. Loading package containers-0.2.0.1 ... linking ... done. Loading package bytestring-0.9.1.4 ... linking ... done. Loading package old-locale-1.0.0.1 ... linking ... done. Loading package old-time-1.0.0.2 ... linking ... done. Loading package filepath-1.1.0.2 ... linking ... done. Loading package Win32-2.2.0.0 ... linking ... done. Loading package directory-1.0.0.3 ... linking ... done. Loading package process-1.0.1.1 ... linking ... done. Loading package pretty-1.0.1.0 ... linking ... done. Loading package Cabal-1.6.0.3 ... linking ... done. Preprocessing library HGL-3.2.0.0... Building HGL-3.2.0.0... Graphics\HGL\Key.hs:57:7: Could not find module `Graphics.Win32': it is a member of the hidden package `Win32-2.2.0.0' Use -v to see a list of the files searched for. *** Exception: ExitFailure 1
該当部分のソースを見ると、ただ、import してるだけです。そのモジュールを ghci上から import すると、何の問題もなく import できます。そこで、ソースの 該当行を消してしまいました。
これを、丹念に繰り返した所、進展はありましたが、下記の所でちから尽きてしまいました。 どなたか、チャレンジしませんか?
c:\sakae>cd HGL-3.2.0.0\ c:\sakae\HGL-3.2.0.0>runghc Setup.hs build Preprocessing library HGL-3.2.0.0... Building HGL-3.2.0.0... [ 3 of 26] Compiling Graphics.HGL.Internals.Types ( Graphics\HGL\Internals\Types.hs, dist\build\Graphics\HGL\Internals\Types.o ) Graphics\HGL\Internals\Types.hs:50:26: Not in scope: `timeGetTime'