Haskell第2回 多相性(ポリモーフィズム)への理解を深める

    • Haskellは型付きλ計算(Wiki)に基づく関数型プログラミング言語
      • 関数の入出力の型をかっちり決めている、と言う意味
    • 前の記事で作成した、"repeated"関数にも型がついている
    • それを表示させるためのコマンドが":type"
Prelude> let repeated f n = \x -> (iterate f x) !! n
Prelude> :type repeated
repeated :: (a -> a) -> Int -> a -> a
      • "(a -> a) -> Int -> a -> a"が型表示
      • "repeated"関数は、引数としてf,n,xを受け取って値を返すので、3つの引数と1つの返り値との、併せて4個について型が決まっている必要がある
        • "(a -> a)"が、初めの引数fの型:fは関数であるから、この関数は、引数を1つ取って、値を1つ返す関数であることがわかる
        • "(a -> a)"に引き続く "Int"が次の引数nの型
        • "(a -> a)" と "Int"の間の "->"は区切り文字(のようなもの)
        • 引き続く"a"がxの型であり
        • 最後の"a"が返り値の型である
  • 多相性
    • 前の話で型が"a"と表示されていた
    • "a"って何?、である
    • あるときは、実数、あるときは整数と「多相」な取扱いをしたいときには、型を「がっちり」決めず、その都度変わる型にしておくことも便利。そのための仕組み
    • ただし、型定義で、aはなんでもよくなるが、一つの関数の型定義の中で繰り返して使われるaはつながっている限りは同じ型になる(はず)
  • 型を決めつけてみる
    • "repeated"関数を作るときに、型の定義を決めて作ることもできる
repeatedInteger :: (Int -> Int) -> Int -> Int -> Int
repeatedInteger f n = \x -> (iterate f x) !! n
    • この第1行のように、型を指定して作る"repeatedInteger"関数は、指定していない引数を取れなくなる
Prelude> :load "repeatedInteger.hs"
[1 of 1] Compiling Main             ( repeatedInteger.hs, interpreted )
Ok, modules loaded: Main.
*Main> repeatedInteger (+2) 3 5
11
*Main> repeatedInteger (+2.1) 3 5

<interactive>:1:19:
    No instance for (Fractional Int)
      arising from the literal `2.1'
    Possible fix: add an instance declaration for (Fractional Int)
    In the second argument of `(+)', namely `2.1'
    In the first argument of `repeatedInteger', namely `(+ 2.1)'
    In the expression: repeatedInteger (+ 2.1) 3 5
*Main> :type repeatedInteger
repeatedInteger :: (Int -> Int) -> Int -> Int -> Int