LYH 7.10 Functor 型クラス
7.10 Functor 型クラス
1.序文
- Functorはどのような型クラスか。
- Functor型クラスに属している型の例を1つあげよ。
- Functor型クラスの実装を示せ。
- 3.中のfmapを読み、どのような関数か説明せよ。
- リストに対するFunctorインスタンス宣言を示せ。
2.MaybeはFunctorだよ、たぶん
- MaybeをFunctorのインスタンスとして宣言するコードを書け。
3. TreeもFunctorの森に
4. EitherはFunctorであるか否か
- Functor型クラスは型引数をいくつ要求するか。
- Either a bは型引数を2つ要求する。これはファンクターに出来るだろうか。どのようにすればよいか。
- 標準ライブラリのControl.Monad.Instances内で、Either aはどのように定義されているか。
- fmapがEither aに特化していたとして、型シグネチャを書け。
- fmapがRightを優先する(?)ことをなんというか。
LYH 7.8 型クラス 中級講座
7.8 型クラス 中級講座
1. 序文
- 型クラスはインターフェースのようなものである。型クラスはどのような振る舞いを定義するか。例を3つあげよ。
- 型クラスの振る舞いは何を定義することで得られるか。
- Eqは、(3.1)が出来る値の型クラスである。Eqはどのような関数(メソッド)を定義しているか。(3.2)
- 標準ライブラリにおけるEqの定義を書け。
class Eq a where
と宣言して、クラスの中で(==) :: a -> a -> Bool
と型宣言する。関数の型は何か。
2. 交通信号データ型
- 値としてRed, Yellow, Greenをもつ交通信号の状態を定義する型TrafficLightを定義し、Eqのインスタンスを自動導出を用いずに作れ。
- クラスを宣言したときには、
==
を定義するのに/=
を使い、/=
の定義には==
を用いた。インスタンス宣言では、どちらか一方を上書きすれば良い。これは型クラスのなんと呼ばれる概念か。 - Showの最小完全定義を満たすように、型TrafficLightををShowのインスタンスにするコードを書け。このとき、例えば値
Red
なら"Red light"
と表示されるようにせよ。
3. サブクラス化
class (Eq a) => Num a where
と書かれたとき、Num
とEq
にはどのような関係があるか。- 型クラス宣言に何をつけるとサブクラスを作ることが出来るか。
4. 多相型を型クラスのインスタンスに
続きを読むLYH 7.7 再帰的なデータ構造
代数(的)データ型の3種類を言え。( 1 )
リストは ( 2 ) または ( 3 ) のいずれかの値を取るデータ構造である。
代数データ型を使って独自のリスト型 List a を実装せよ。( 4 )
( 4 ) をレコード構文を用いて書け。( 5 )
Cons とは ( 6 ) を言い換えたものである。Haskell標準の ( 6 ) は、値とリストをとってリストを返す ( 7 ) である。( 6 ) には、( 8 ) と ( 9 ) の2つのフィールドがあるといえる。
リストの改善
記号文字だけを使って関数に名前をつけると ( 10 ) になる。値コンストラクタも ( 11 ) であるので同様。
ただし、値コンストラクタの名前は ( 12 ) で始まる必要がある。
結合性宣言を infixr 5 とした上で、Cons a (List a) と同等の値コンストラクタ a :-: (List a) を定義せよ。( 13 )
結合性宣言は必須ではないので、これを除けば Cons a (List a) と同等という意味。結合性宣言を省略した演算子はすべて infixl 9 となる。
標準のリストにおける ++ と同等の、独自のリスト型List aにおける ^++ の定義を書け。ただし、結合性宣言の数字は 5 である。( 14 )
パターンマッチとは、( 15 ) をマッチさせることに他ならない。なので、( 14 ) のコードにおいて ( 16 ) というパターンマッチを使うことができる。
パターンマッチは ( 15 ) であれば何に対してでも使えるので、(今まで :-: などの中置コンストラクタについてパターンマッチさせてきたが)通常の前置コンストラクタもパターンマッチできる他、( 17 ) や ( 18 ) といったものもパターンマッチできる。これらは数値型や文字型の ( 15 ) だからからである。
木を植えよう
二分木のデータ型Tree aを実装せよ。ただしShow型のインスタンスであるものとする。( 19 )
二分木を作るための2つの関数を実装せよ。( 20 )
ある要素が二分木に属しているか判定する関数を作れ。( 21 )
リストから要素を1つずつ辿って値を生成する操作は畳み込みを使うのが便利である。畳み込みを用いて、リストnumsから生成された木numsTreeを作れ。( 22 )
LYH 7.6 型シノニム
新しい型を作る = ( 1 ) キーワード
型同義名(型シノニム)を作る = ( 2 ) キーワード
例えば、Stringは以下ように型シノニムとして定義されている。
type String = [Char]
電話帳を定義してみよう。
type PhoneNumber = String type Name = String type PhoneBook = [(Name, PhoneNumber)] pbook :: PhoneBook pbook = [ ("betty", "555-2938"), ("bonnie", "452-2928"), ... ] inPhoneBook :: ( 3 ) inPhoneBook name pnumber pbook = (name, pnumber) `elem` pbook
型シノニムの多相化
type AssocList ( 4 ) = [(k, v)]
とすることで、型引数を取ることができる。AssocListは ( 5 ) である。
以下の2つは同義
type ( 6 ) type IntMap v = Map.Map Int v
そこを左に行って、すぐ右へ
Either a b は( 7 )を2つとるデータ型である。
Left, Right はそれぞれ( 8 )である。
ghci> Right 20 ( 9 ) ghci> Left "w00t" ( 10 ) ghci> :t Right 'a' ( 11 ) ghci> :t Left True ( 12 )
Left True の型を評価すると ( 12 ) となっていることがわかる。Left ( 8 ) で作った値なので、1つ目の型引数は Bool に決まっているが、2つ目の型引数は ( 13 ) のまま残っている。これは、Nothing という値に ( 14 ) という型が付くのと同じ理屈である。
Nothing は何故失敗したかの情報を持つことはできない。これを持てるようにするために、普通は ( 15 ) 型の返り値を使う。ここで、( 16 ) は失敗が起こった場合に何であるかを伝えてくれる型、( 17 ) は、成功した計算の型である。したがって、エラーは ( 18 ) を、結果は ( 19 ) を使って表す。
ロッカーの割当のコードを書け。( 20 )
ロッカーを表すMapから暗証番号を検索する関数を作りたい。
関数が失敗するパターンが、( 21 ) と、( 22 ) の2通りあるので、( 23 ) 型で表すようにする。
実際に、暗証番号を検索する関数を作れ。( 24 )