2011-10-01から1ヶ月間の記事一覧

「Write Yourself a Scheme in 48 Hours」 を写経してみる(13) : Scheme関数の定義

48時間でSchemeを書こう/Scheme関数の定義 http://jonathan.tang.name/files/scheme_in_48/code/listing9.hs まず、 LispVal型のデータを見ますと二つの型が追加されています。 data LispVal = Atom String | List [LispVal] | DottedList [LispVal] LispVal…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(12) : 「エラーチェックと例外」をもっと

Env の内容が表示出来るようになったところで、 defineVarを動かしてみたいのですが Show インスタンスがないので表示できません。 > env <- nullEnv > showEnv env -- > [] > defineVar env "y" (Number 9) <interactive>:1:0: No instance for (Show (IOThrowsError Lis</interactive>…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(11) : Env の内容がみたい

「Write Yourself a Scheme in 48 Hours」 を写経してみる(9) : 変数の追加と割り当ての中で define, set!で変数が定義、変更される様子を覗きたかったのですが、IORef が入れ子になっていて簡単には覗けません。そこで、IORefの練習に表示する関数を作って…

Error Monad (Exception Monad)

モナドのすべて Haskell におけるモナドプログラミングの理論と実践に関する包括的ガイドの Error モナドを写経してみました。 import Monad import System import Control.Monad.Error import Char import Debug.Trace -- 表示できるように deriving Showを…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(10) : cdr の評価が間違っている。

「Write Yourself a Scheme in 48 Hours」 を写経してみる(6) : 評価その2の中で cdr を評価する部分があったのですけれども、kazu-yamamoto さんの「HaskellでScheme」という記事の中で「cdr の定義が間違っている」記述を見つけました。 cdr [DottedList …

「Write Yourself a Scheme in 48 Hours」 を写経してみる(9) : 変数の追加と割り当て

Write Yourself a Scheme in 48 Hours/Adding Variables and Assignment http://jonathan.tang.name/files/scheme_in_48/code/listing8.hs まず、評価をするeval関数から見ていきます。 eval :: Env -> LispVal -> IOThrowsError LispVal eval env val@(Stri…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(8) : REPLを構築する。

Write Yourself a Scheme in 48 Hours/Building a REPL http://jonathan.tang.name/files/scheme_in_48/code/listing7.hs REPLとは Read-eval-print loopの略。読み込んで評価をしてそれを表示・・・その繰り返しをする対話型評価環境を作ります。 import IO…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(7) : Equal? と弱いタイピング: 不均一なリスト

タイトルが長すぎるのが気になります・・・。 Write Yourself a Scheme in 48 Hours/Evaluation, Part 2 http://jonathan.tang.name/files/scheme_in_48/code/listing6.4.hs まず、ghci listing6.4.hs とするとエラーになります。 $ ghci listing6.4.hs GHCi…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(6) : 評価その2

Write Yourself a Scheme in 48 Hours/Evaluation, Part 2 http://jonathan.tang.name/files/scheme_in_48/code/listing6.3.hs primitives :: [(String, [LispVal] -> ThrowsError LispVal)] primitives = [("+", numericBinop (+)), ("-", numericBinop (-)…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(5) : エラーチェックと例外

Write Yourself a Scheme in 48 Hours/Error Checking and Exceptions http://jonathan.tang.name/files/scheme_in_48/code/listing5.hs -- readExpr は (Right) パースに成功するとパースした値を返す。 -- 失敗のときは (Parser err) の例外を投げる。 rea…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(3)

http://jonathan.tang.name/files/scheme_in_48/code/listing4.3.hs 今回は基本的なS式の評価です。 評価する様子が見えるようにtraceを入れてみました。 内部データが見えるように Show インスタンスをコメントで無効にし、deriving Show を追加しました。 …

「Write Yourself a Scheme in 48 Hours」 を写経してみる(4) : ($) を使って関数を引数とする関数を作る。

Write Yourself a Scheme in 48 Hours/Evaluation, Part 1の中に次に示す apply 関数が定義してあります。 apply 関数は (+ 1 2 3) のような関数のときに func:"+"、 args:[Number 1,Number 2,Number 3] として、argsにfuncを適用させるための関数です。 loo…

「Write Yourself a Scheme in 48 Hours」 を写経してみる(2)

HaskellでLispを書く日記を読んでいたのですけれども、私の能力では Cons のネストを追うのが大変なので、以前に写経した「『Write Yourself a Scheme in 48 Hours』を写経してみる」の続きをやってみます(こっちは出来ない英語なので大変なのですが)。 まず…

「HaskellでLispを書く日記」を読む(2)

「HaskellでLispを書く日記 / evalの作成(変数編) Lisp は定義された値をテーブルに登録し、それを検索しているようです。 import Text.ParserCombinators.Parsec data Sexp = Nil | Symbol String | N Integer | Cons Sexp Sexp deriving Show {- リスト…

「HaskellでLispを書く日記」を読む(1)

「HaskellでLispを書く日記」を写経しながら読んでみます。 import Text.ParserCombinators.Parsec import Debug.Trace data Sexp = Nil | Symbol String |Cons Sexp Sexp deriving Show Show、Read クラスのインスタンスも定義してありますがSexp型データの…

Parsecにちょっと触ってみる(9): S式っぽい計算機

Parsec, 高速なコンビネータパーサ 練習にS式っぽい計算機を作ってみました。 import Text.ParserCombinators.Parsec import Data.List -- sexpは'('と')'に囲まれていて、"*/+-"のどれかの次にスペースがあって、 -- スペースで区切られたexprがある。 sexp…

モナドって何だろう(2) List モナド

List モナドは長さの変化するリストの演算を連鎖させて行うときに使います。 例としてフィボナッチ数を求めてみます。 フィボナッチ数 1つがいの兎は、産まれて2か月後から毎月1つがいずつの兎を産む。 1つがいの兎は1年の間に何つがいの兎になるか?つがい…

Maybe ユーティリティ

Maybe 型を便利に操作する関数「Haskell 98 言語とライブラリ 改訂レポート / 18 Maybe ユーティリティ」を写経してみます。今まで自分で作っていました・・・Orz isJust :: Maybe a -> Bool > isJust (Just 10) -- > True > isJust Nothing -- > False isNo…

モナドって何だろう

モナドを使うと何が良いのか、モナドを使った場合と使わない場合を比較してみます。 関数プログラミングはデータに何度も関数を適用することにより希望する出力を得ます。データを引数として関数を適用し、その結果に関数を適用し・・・と関数プログラミング…

Parsecにちょっと触ってみる(8): try はパースに失敗しても入力を消費してないように振る舞う。

Parsec, 高速なコンビネータパーサ 「string "(a)" string "(b)"」は"(a)" または "(b)" にマッチすることを期待したパーサ。 "(a)" にはマッチする > :m Text.ParserCombinators.Parsec > parseTest (string "(a)" <|> string "(b)") "(a)" -- > "(a)" "(b)…

FizzBuzz で学ぶ

Haskell で FizzBuzz。 再帰 で recFizzBuzz :: Int -> [String] recFizzBuzz = reverse.recFizzBuzz' recFizzBuzz' :: Int -> [String] recFizzBuzz' 0 = [] recFizzBuzz' n | n `mod` 15 == 0 = "FizzBuzz":recFizzBuzz' (n-1) | n `mod` 3 == 0 = "Fizz":…

Parsecにちょっと触ってみる(7): 連接と選択

Parsec, 高速なコンビネータパーサ do 記法を使えば連続してマッチするパーサを作ることが出来ます(連接)。 > :m Text.ParserCombinators.Parsec > parseTest (char 'a') "abc" -- > 'a' > parseTest (do{char 'a';char 'b'}) "abc" -- > 'b' > parseTest (d…

foldl1,foldr1,scanl1, scanr1

Haskell で Ruby の [a, b, c].join(x) と同等のことをするには intersperse が便利。 > concat $ Data.List.intersperse "-" ["abc", "def", "ghi"] -- > "abc-def-ghi" -- intersperse を自分で作るとこんな感じ。 intersperse' :: a -> [a] -> [a] inters…

Parsecにちょっと触ってみる(6):Parsec で掛け算

しばらくやっていなかったのですっかり忘れました。Parsec, 高速なコンビネータパーサ を参考にして簡単な掛け算。 パースは何をするものかと言うと、数字文字列から本物の数字、S式の文字列から本物のS式、配列の文字列から本物の配列を作ります。文字列か…