HaskellでSchemeを書く#3
評価器の作成
今回から評価器の作成に移る。
まず最初に引っかかるのが以下。
instance Show LispVal where show = showVal
Show
型クラスの中に、LispVal
を受け取ったときの動作を加えますよ、という意味合いらしいのだけど、どうやらこのあたりで型クラスについてさらりとでも触れたほうが良いのではないかと思う。
Haskellにおける型クラスとは、データ型に対する振る舞いの集合、のようだ。ある型クラスのインスタンスに属していれば、型クラス特有の関数(クラスメソッド)を利用出来る。また、そのメソッドの振る舞いはデータ型ごとに指定出来る、という理解。
とりあえず試す。
何か引数を2つとり、文字列を返すメソッドを持つ、型クラスをつくろう。
Prelude> class Hoge a where (<?>) :: Show a => a -> a -> String; a<?>b = "null" Prelude> :t (<?>) (<?>) :: (Show a,Hoge a) => a -> a -> String Prelude>
メソッドの宣言部分(シグネチャというらしい。)は必ず必要で、またデフォルト動作の定義は任意。今回はデフォルト動作は"null"
を返すことにしておいた。
そして、今現在は、型クラスを抽象的に宣言しているだけなので、実際の動作を記述していく。
instance Hoge String where x:xs <?> b = x:b
こんな風に宣言したところでエラー。String
はtype String = [Char]
と宣言されているからで、[]
は代数的データ型(!!)なので、[] Char
みたいに解釈されるけども、Char
は型変数じゃないから受け付けないよ、ということらしい。(参考'Why can I not make String an instance of a typeclass?' - Stack Overflow)
これの対策は、newtype newString = newString String
みたいにラッピングする型を宣言することで回避出来る。newtype
は型クラスのインスタンスを新しく宣言し直せるらしい。ちなみに、type
はシノニム(ただのエイリアス?)としての意味しかないので、この2つは似て非なるもの。
Prelude> instance Hoge Integer where a <?> b = show a ++ " ? " ++ show b Prelude> instance Hoge Char Prelude> 1<?>2 "1 ? 2" Prelude> 'a'<?>'b' "null"
ということで、型クラスについてちょっとだけ理解した。
次は例外とかのハンドリング!