10.8 練習問題 以下のインスタンス宣言を完成させよ。 instance Monad Maybe where ... instance Monad [] where ... ここで[]は、[a]から型変数を取り除いたリスト型を表す。 ヒント:最初に、それぞれのインスタンスのメソッド return と >>= の型を考えよ…
10.8 練習問題 関数 isTaut と、前の二つの章で定義したパーサーと対話プログラムのライブラリを用いて、対話的に恒真式か検査する関数を実装せよ。ユーザーがキーボードからわかりやすい文法で命題を入力できるようにすること。 ヒント:8章で定義した数式…
10.8 練習問題 再帰と関数addを用いて、自然数の乗算関数 mult :: Nat -> Nat -> Nat を定義せよ。 これは楽勝。(10.3で定義したNatはゼロも自然数だったことを思い出して) module TenEightOne where import TenThree mult :: Nat -> Nat -> Nat mult Zero…
10.6 クラスとインスタンスの宣言 前にも書いたけど、Haskellのクラスは型クラスで、型クラスのインスタンスは型。 最初はBool型がEqクラスを実装する例。自分でも手を動かしたかったので、Bool型とEqクラスを自分で定義してみる。演算子はちょっと悩んだけ…
10.5 仮想マシン 二つ目の長い例題として、整数と加算演算子からなる単純な数式の型と、この数式を評価して整数にする関数を考えよう。 data Expr = Val Int | Add Expr Expr value :: Expr -> Int value (Val n) = n value (Add x y) = value x + value y …
10.4 恒真式 命題論理式を表す型を作り、与えられた命題が恒真式(式に含まれる変数の値に関係なく、常に真となる式)かどうかを判定する関数を書く。 まずは命題の型を定義。 真理値(True, False)Const Bool 変数(A, B, ... , Z)Var Char 否定(¬)Not Prop …
前回の日記でdataによる型定義を学んだけど、これ、もっと掘り下げておくべきだったな。 引数なしのデータコンストラクタだと列挙型みたいなもの。これはOK。たとえば、Bool型の要素がTrueとFalse、といった形でこれまでも登場している。 でも引数ありのデー…
10.1 typeによる型宣言 typeキーワードは型のエイリアスに名前をつける方法。再帰定義はできない。 type Assoc k v = [(k,v)] find :: Eq k => k -> Assoc k v -> v find k t = head [v | (k',v) <- t, k == k'] newtypeキーワードは教科書に出て来てないな…
9.9 練習問題 練習問題5は「グラフィック・ライブラリを用いて」とか書いてあって面倒なのでパス。Windowsで動かなかったりするし。 ニムはボードを使うゲームである。ボードには、番号の付いた行が五つあり、はじめは星が以下のように並べてある。 1:***** …
9.9 練習問題 ライフゲームのボードを対話的に作成したり、変更したりできるエディターを作れ。 9.7で写経したライフゲームを修正して、ボードサイズを可変にできるようにしてやったぜ。 module NineNineFour where import System.IO import NineFive getCh …
http://d.hatena.ne.jp/rst76/20120204/1328362118 F#の環境を作るのが面倒という声も上がっているけど、 オンラインでやりゃいいじゃない。パンがなければお菓子を食べればいいじゃない。 というか、Linux/Mac/Solarisな人ならmonoを入れれ。 http://www.go…
9.9 練習問題 ライフゲームは、世代ごとに画面全体をクリアするので、動かす環境によっては、動きがちらつくかもしれない。それを防止するために、状態が変わったところだけ表示し直すようライフゲームを変更せよ。 うーん。リモートターミナルとかだとちら…
9.9 練習問題 エラーの際に単にビープ音を鳴らすのではなく、エラーの位置が分かるように電卓を変更せよ。パーサーは消費しなかった文字列を返すという性質を活用するとよい。 「エラーの位置がわかるように」というのが何を求めているのかよくわからないが…
では実際に解いてみよう。 9.9 練習問題 アクション getLine に、削除キーで文字を消去できる機能を加えたアクション readLine :: IO String を定義せよ。ヒント:一文字削除するための制御文字は "\DEL"、一文字戻るための制御文字列は "\ESC[1D" である。 …
さて、getChの前から怪しいと思ってたのだけど、getCharがEnterを押すまでキーを認識しない。 いろいろ調べると、バッファリングモードの問題らしく import IO do hSetBuffering stdio NoBuffering とかなんとかそういうのをやれと書いてある。が、やっても…
9.9 練習問題 今日は時間がないので、問題文を写すだけにしておく。 アクション getLine に、削除キーで文字を消去できる機能を加えたアクション readLine :: IO String を定義せよ。ヒント:一文字削除するための制御文字は "\DEL"、一文字戻るための制御文…
もともと、俺のHaskell学習の目標は、“http://d.hatena.ne.jp/rst76/20100706/1278430517を全部理解できるようになること”だったわけで、それは今でも変わっていない。 で、Haskellはだんだんわかって来たけど、“木探索から CPS にすることで効率化”が腑に落…
ライフゲーム さて、9.7はライフゲームの実装。 ひたすら写経。9.5で実装した関数群を使っている。 module NineSeven where import NineFive width :: Int width = 5 height :: Int height = 5 type Board = [Pos] glider :: Board glider = [(4,2), (2,3), …
9.6の計算機プログラムの中でgetChという関数が出てきていて、コンパイルに通らないのでgetCharに置き換えてたんだけど、 Hugs, but can be defined in Haskell as follows: >|haskell| import System.IO getCh :: IO Char getCh = do hSetEcho stdin False …
というわけでminttyからhugsを起動する方法にしたら捗った。 あと、今までは全部1ファイルでやろうとしていたが、色々無理が出てきたのでモジュール化した。 module NineSix where import Parsing import Expr import NineFive box :: [String] box = ["+---…
MSYS上のminttyからhugsを起動すればいいということで、今後はそうする。
Haskellにくわしい後輩から「F#教えてください」と言われたが、俺もわからんのよ。F#のコードを書いたことがないので。 でもそれじゃつまらないので、Haskellの勉強で学んだ知識をもとにF#に挑戦してみた。 いろいろ試行錯誤した結果がこれだ。One, Two Thre…
そういえばうちにはMac Miniがあったんだった。ずっとWindowsばかり起動していたから忘れていた。 てなわけでMacPortsをインストールした後Hugsをインストール。Windowsからはteraterm経由でアクセス。 おお、快適。エスケープシーケンスも動くし。
IOモナドで計算機はいいんだけどさあ。Windowsではちょっとねえ。前回書いたように、エスケープシーケンスは動かないし、グラフィクスライブラリ(HGLとかSOEとか)は動かないし。やる気が…… VirtualBoxかなにかでUbuntuとか動かして、そこでHaskellをやるか………
仕事が忙しくて書けてなかったけど、忘れたわけではない。 入出力の型 IO aの簡易説明、っていうかこのWorldを使った説明はごまかしだよなあ。 写経したコードを試しに実行する時に困るんだよねえ。 カリー化によって(最近、ScalaやGroovy界隈で話題だった…
教科書の第9章をパラパラと読んだら、第9章はIOモナド。しかも第8章のパーサーを使用するようだ。 てことは、第8章のパーサーを本物のモナドで定義しておかないと、サンプルコードを実行できないと思われる。 仕方なく、教科書のサイトから第8章のパーサーを…
演習問題 問題7 累乗を定義。 term' :: Parser Int term' = pow >>- \p -> (symbol "*" >>- \d -> term' >>- \t -> return' (p * t)) +++ (symbol "/" >>- \d -> term' >>- \t -> return' (p `div` t)) +++ return' p pow :: Parser Int pow = factor >>- \f…
演習問題 問題6 おれおれbindとreturnで。 expr' :: Parser Int expr' = term' >>- \t -> (symbol "+" >>- \d -> expr' >>- \e -> return' (t + e)) +++ (symbol "-" >>- \d -> expr' >>- \e -> return' (t - e)) +++ return' t term' :: Parser Int term' =…
演習問題 問題4 expr | term ______|________ | | | factor * term | _____|___ nat | | | | factor * term 2 | | nat factor | | 3 nat | 4 expr | term ___________|_____ | | | factor * term _______|________ | | | | factor ( expr ) | ____|____ nat …
旅行に行ったので間があいてしまった。 数式 相変わらずdo記法を使わずにオレオレbindとオレオレreturnで書いてみる。 expr :: Parser Int expr = term >>- \t -> (symbol "+" >>- \d -> expr >>- \e -> return' (t + e)) +++ return' t term :: Parser Int …