LYH 7.10 Functor 型クラス

7.10 Functor 型クラス

1.序文

  1. Functorはどのような型クラスか。
  2. Functor型クラスに属している型の例を1つあげよ。
  3. Functor型クラスの実装を示せ。
  4. 3.中のfmapを読み、どのような関数か説明せよ。
  5. リストに対するFunctorインスタンス宣言を示せ。

2.MaybeはFunctorだよ、たぶん

  1. MaybeをFunctorのインスタンスとして宣言するコードを書け。

3. TreeもFunctorの森に

  1. fmapをTree a型専用の関数と思って型シグネチャを書け。
  2. TreeをFunctorのインスタンスとして宣言するコードを書け。

4. EitherはFunctorであるか否か

  1. Functor型クラスは型引数をいくつ要求するか。
  2. Either a bは型引数を2つ要求する。これはファンクターに出来るだろうか。どのようにすればよいか。
  3. 標準ライブラリのControl.Monad.Instances内で、Either aはどのように定義されているか。
  4. fmapがEither aに特化していたとして、型シグネチャを書け。
  5. fmapがRightを優先する(?)ことをなんというか。
続きを読む

LYH 7.9 YesとNoの型クラス

7.9 YesとNoの型クラス

  1. 様々な型の真理値判定を可能とするためのYesNo型を宣言せよ。
  2. 1.に関して、0は偽、それ以外は真と解釈するように数に関してのインスタンスを定義せよ。
  3. 空リストは偽、そうでなければ真とするようにリストに関してのインスタンスを定義せよ。
  4. 3.のインスタンス宣言について、[a]の部分を同じ意味で別の表記に変更することが出来る。どのように変えればよいか。
  5. Boolインスタンスを定義せよ。
  6. 5.で用いたidとは何か。
  7. Maybe aインスタンスを定義せよ。
  8. YesNo値をとり、好きな型の値の2つのうち1つを返す関数yesNoIfを定義せよ。
続きを読む

LYH 7.8 型クラス 中級講座

7.8 型クラス 中級講座

1. 序文

  1. 型クラスはインターフェースのようなものである。型クラスはどのような振る舞いを定義するか。例を3つあげよ。
  2. 型クラスの振る舞いは何を定義することで得られるか。
  3. Eqは、(3.1)が出来る値の型クラスである。Eqはどのような関数(メソッド)を定義しているか。(3.2)
  4. 標準ライブラリにおけるEqの定義を書け。
  5. class Eq a whereと宣言して、クラスの中で(==) :: a -> a -> Boolと型宣言する。関数の型は何か。

2. 交通信号データ型

  1. 値としてRed, Yellow, Greenをもつ交通信号の状態を定義する型TrafficLightを定義し、Eqのインスタンスを自動導出を用いずに作れ。
  2. クラスを宣言したときには、==を定義するのに/=を使い、/=の定義には==を用いた。インスタンス宣言では、どちらか一方を上書きすれば良い。これは型クラスのなんと呼ばれる概念か。
  3. Showの最小完全定義を満たすように、型TrafficLightををShowのインスタンスにするコードを書け。このとき、例えば値Redなら"Red light"と表示されるようにせよ。

3. サブクラス化

  1. class (Eq a) => Num a whereと書かれたとき、NumEqにはどのような関係があるか。
  2. 型クラス宣言に何をつけるとサブクラスを作ることが出来るか。

4. 多相型を型クラスのインスタンス

  1. 型コンストラクタMaybeを型クラスEqのインスタンスとする例を1つ書け。
  2. 型クラスYourTypeClassのインスタンスの詳細を知るにはGHCiで何と入力すればよいか。
続きを読む

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 )

続きを読む