私のためのHaskell〜ひたすら原点回帰〜その2 値・演算の階層構造、型・演算の階層構造

  • 演算を拡張する
  • 前の記事では、「あ」は型によって集合の要素となり、「あ」のうちの演算は値を取って値を返すものであったので、「型」を取って「型」を返す具体的な変化の集合でもあった
  • 「○○を取って、××を返す」というメカニズムで「○○」と「××」は「型を持った『あ』」であったが、せっかくメカニズムがあるので、それを別の何かにも適用してもよいだろう
  • ここまでの世界にあるのは「あ」である「要素・演算」と、それらを束ねた「型」とである
  • 「○○を取って、××」を返すの「○○」と「××」とに、「値」「演算」「型」をあてはめることにする
  • 要素を2つ(またはn個)取って演算をすると新しい要素ができることがある
  • 演算を2つ(またはn個)取って演算をすると新しい演算ができることがある
    • 関数合成はこれにあたる
Prelude> :type (.)
(.) :: (b -> c) -> (a -> b) -> a -> c
    • どんな関数を与えても特定の関数を返すような関数も作れる
data A = A1 | A2 deriving Show
data B = B1 | B2 deriving Show
let myfa :: A -> A; myfa = \ A1 -> A2
let myfb :: B -> B; myfb = \ B1 -> B2
let myfab :: A -> B; myfab = \ A2 -> B1
let myff :: (a->b) -> (A->A); myff = \_ -> myfa
myff (myfa A1)
:type myff
Prelude> data A = A1 | A2 deriving Show
Prelude> data B = B1 | B2 deriving Show
Prelude> let myfa :: A -> A; myfa = \ A1 -> A2
Prelude> let myfb :: B -> B; myfb = \ B1 -> B2
Prelude> let myfab :: A -> B; myfab = \ A2 -> B1
Prelude> let myff :: (a->b) -> (A->A); myff = \_ -> myfa
Prelude> (myff myfa) A1
A2
Prelude> myff myfa A1
A2
Prelude> :type myff
myff :: (a -> b) -> A -> A
    • これは関数の2項演算。関数の1項演算・0項演算、n項演算とかもできるだろう
  • 関数のn項演算は複雑だが、値のn項演算と基本的には同じで、併せて「『あ』を2つ(またはn個)取って演算をするとあたらしい『あ』ができる」とまとめられる
  • 型を2つ(またはn個)取って演算をすると新しい型ができることにする
    • これを代数的型と(Haskellでは)呼ぶ
      • 型Aを2つを持つ型FAを作る
      • そのFAという型には2通りの値の作り方があって、FA1 A AかFA2 A Aである。
      • このFA1,FA2というのはA型の引数を2つ取ってFA型を返す関数。
      • このFA型にはA型の要素が2つ帰属しているが、それを取り出すこともできる。
data A =A1 | A2
data FA = FA1 A A| FA2 A A
let fa1 :: FA; fa1 = FA1 A1 A1
let pick1st :: FA -> A; pick1st (FA1 x y)  = x
:type fa1
:type pick1st
:type pick1st fa1
Prelude Control.Arrow> data A =A1 | A2
Prelude Control.Arrow> data FA = FA1 A A| FA2 A A
Prelude Control.Arrow> let fa1 :: FA; fa1 = FA1 A1 A1
Prelude Control.Arrow> let pick1st :: FA -> A; pick1st (FA1 x y)  = x
Prelude Control.Arrow> :type fa1
fa1 :: FA
Prelude Control.Arrow> :type pick1st
pick1st :: FA -> A
Prelude Control.Arrow> :type pick1st fa1
pick1st fa1 :: A