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