2つの関数を f と g とすれば f . g と単純に行くのは g の引数が1つの場合だけ。2つ以上の引数をとる場合にはちょっと複雑になる。次のような関数で確かめてみる。
f a = a:[] g a = a:[] g2 a b = a:b:[] g3 a b c = a:b:c:[]
まずは簡単な f と g
*Main> :t f . g f . g :: a -> [[a]]
引数を2つとる g2 に対して同じようにやると
*Main> :t (f . g2) (f . g2) :: a -> [a -> [a]]
こんな型になって2つの引数をうまく追い出せない。
*Main> (f . g2) 1 2 <interactive>:1:0: Couldn't match `[a -> [a]]' against `t -> t1' Expected type: [a -> [a]] Inferred type: t -> t1 Probable cause: `(f . g2)' is applied to too many arguments in the call ((f . g2) 1 2) In the definition of `it': it = (f . g2) 1 2
追い出してやるには,関数合成を2段階にする。
*Main> :t ((f .) . g2) ((f .) . g2) :: a -> a -> [[a]] *Main> ((f .) . g2) 1 2 [[1,2]]
引数が3つの場合には3段階。
*Main> :t (((f .) .) . g3) (((f .) .) . g3) :: a -> a -> a -> [[a]] *Main> (((f .) .) . g3) 1 2 3 [[1,2,3]]
逆に1つ目の関数のほうが複数引数の時は単純に合成できる。
*Main> :t g3 . f g3 . f :: a -> [a] -> [a] -> [[a]]
ただし,引数のほうがややこしい。上の例で行くと1つ目の引数は f の引数,2つ目以降が g3 の2番目3番目の引数となる。こうすればわかりやすい。
g3 (f a) b c
実行。
*Main> (g3 . f) 1 [2] [3] [[1],[2],[3]]
じゃあ,引数が3つと2つならどうだ。
*Main> :t (g3 .) . g2 (g3 .) . g2 :: a -> a -> [a] -> [a] -> [[a]] *Main> ((g3 .) . g2) 1 2 [3] [4] [[1,2],[3],[4]]
ああ,ややこしい。