プログラミングHaskell第2版 3章メモ書き

3章まできた。今の所毎週1章ずつ進められているので順調だが、この先どうなる事やら。。。 社内勉強会もスキップ無しで毎週開催できているので、こちらも続けたいところ。

第3章 型と型クラス

互いに関連する値の集合

例: Bool型 ... False, Trueという二つの真理値が含まれる。「Bool → Bool」型 ... Bool型をBool型に変換する否定演算子notのような関数が全て含まれる。

-- vの型はTである。vは型Tの値である。 v :: T

False :: Bool
True :: Bool
not :: Bool -> Bool

-- 式eを評価すると型Tの値を生成する e :: T

not False :: Bool
not True :: Bool
not (not False) :: Bool

Haskellでは全ての式に必ず型が付き、式の型は型推論という機能によって式を評価する前に決定される。

Haskellでは式を評価する前に型が検査されるので、評価の際には型エラーが起きない。(型安全。ただし評価の際に他のエラーが起きないことを保証しているわけではないので注意

関数型

関数は、ある型の引数を他の型(もしくは引数と同じ型)の結果に変換する。

-- 型T1の引数を型T2の返り値に変換する関数の型を「T1 -> T2」と書く。

not :: Bool -> Bool -- 関数notの型は「Bool -> Bool」である
even :: Int -> Bool -- 関数evenの型は「Int -> Bool」である
add :: (Int, Int) -> Int -- 関数addの型は「(Int, Int) -> Int」である。

カリー化された関数

関数で複数の引数を処理する、タプルを引数に渡す以外の方法。

関数が返り値として関数を返せるという性質を活用する方法。

以下の例のように、1度に1つの引数をとる関数をカリー化されていると表現する。

-- タプルを使って複数の引数を処理する例(カリー化されていない)
add :: (Int, Int) -> Int
add (x, y) = x + y

-- カリー化された関数の例
add' :: Int -> (Int -> Int) -- 関数add'の型は「Int -> (Int -> Int)」である。(Intを引数として受け取って、「Int -> Int」型の関数を返す)
add' x y = x + y
-- xを引数として受け取って、「Intを引数として受け取ってIntを返す関数 ... ①」を返し、
-- ①をyに関数適用してIntを返す。
-- add'は、2つの引数を一度に1つずつ取っている点がタプルを使う例と異なる。

カリー化された関数を扱うときに括弧が過剰になるのを避けるための2つの規則

  1. 型の中の → は右結合
-- 両者は同等
Int -> Int -> Int -> Int
Int -> (Int -> (Int -> Int))
-- Int型の値を引数に受け取って、「Int -> (Int -> Int)」型の関数を返し、
-- 「Int -> (Int -> Int)」型の関数はInt型の値を引数に受け取って「Int -> Int」型の関数を返し、
-- 「Int -> Int」型の関数はInt型の値を受け取りInt型の値を返す
  1. 空白文字を用いて表す関数適用は、必然的に左結合である
-- 両者は同等
mult x y z
((mult x) y) z

多重定義型

1つ以上の型クラス制約をもつ型のこと。

型クラス制約

ある関数がある型の値に適用可能であるという事実を正確に表現するためのもの。

C a という形式で書く。(Cは型クラス名、aは型変数。)

-- +は数値型の値に適用可能であり、数値型の値を引数にとり、「a -> a」型(aは数値型)の関数を返す
(+) :: Num a => a -> a -> a

練習問題の回答はこちら

https://gist.github.com/h-shima/1e6c22c4fa655940009b60b436f0f886