((.) . (.))왼쪽의 (.)를 g, 오른쪽의 (.)를 f라고 둡시다.
let g = (.) :: c -> d
f = (.) :: a -> b
in g . fg . f가 되려면 f의 리턴값을 g가 받아야겠죠. 따라서 c와 b는 같은 타입이 됩니다.
let g = (.) :: b -> d
f = (.) :: a -> b
in g . f그냥 중위 연산자 (.)의 타입을 보자면, 오른쪽 인자는 함수고, 왼쪽 인자는 역시 함수인데, 오른쪽 함수의 결과값이 왼쪽의 함수에 들어오는 형태죠. 그래서
(.) :: (y -> z) -> (x -> y) -> (x -> z)가 됩니다. 같은 말로
(.) :: (y -> z) -> (x -> y) -> x -> z
(.) :: (y -> z) -> ((x -> y) -> (x -> z))가 되죠. 여기에 함수 g와 f를 봅시다.
g :: (gy -> gz) -> ((gx -> gy) -> (gx -> gz))
g :: b -> d
f :: (fy -> fz) -> ((fx -> fy) -> (fx -> fz))
f :: a -> b
type b = (fx -> fy) -> (fx -> fz) -- 실제로 타입 이름엔 첫 글자로 소문자가 올 순 없습니다.
type b = gy -> gz
type gy = fx -> fy
type gz = fx -> fz대입하자면
g :: ((fx -> fy) -> (fx -> fz)) -> ((gx -> (fx -> fy)) -> (gx -> (fx -> fz)))
f :: (fy -> fz) -> ((fx -> fy) -> (fx -> fz))
g . f :: (fy -> fz) -> ((gx -> (fx -> fy)) -> (gx -> (fx -> fz)))괄호를 좀 지워봅시다.
g . f :: (fy -> fz) -> ((gx -> (fx -> fy)) -> (gx -> (fx -> fz)))
g . f :: (fy -> fz) -> ((gx -> fx -> fy ) -> (gx -> fx -> fz ))
g . f :: (fy -> fz) -> (gx -> fx -> fy ) -> (gx -> fx -> fz )
g . f :: (fy -> fz) -> (gx -> fx -> fy ) -> gx -> fx -> fz답은 (b -> c) -> (a -> a1 -> b) -> a -> a1 -> c 였죠?
g . f :: (fy -> fz) -> (gx -> fx -> fy) -> gx -> fx -> fz
g . f :: (b -> c ) -> (a -> a1 -> b ) -> a -> a1 -> c맞힌 거 같네요.
그냥 이런 함수입니다.
((.) . (.)) g f = \a b -> g (f a b)한번 써먹어보죠.
ghci> let dot = ((.) . (.))
ghci> sum [3,4,5,6]
18
ghci> take 4 [3..]
[3,4,5,6]
ghci> let sumTake = sum `dot` take
ghci> sumTake 4 [3..]
18그러니까,
dot g f a b = g (f a b)에서 ((.).(.))를 추출해 봅시다. 그 전에 익혀 두시면 좋은 규칙 하나 알려드리죠.
f (g x) = (f . g) x
\x -> f (g x) = f . g문제로 돌아와서, 맨 끝에 있는 b를 소거하자면
dot g f a b = g (f a b)
dot g f a b = (g . f a) b
dot g f a = g . f a이렇게 되겠네요. 다음으로 a를 소거하고 싶습니다. 어떻게 하면 좋을까요? 여기서부터 돌아올 수 없는 길을 걷게 됩니다. g . f는 (g .) f로 다시 쓸 수 있죠?
dot g f a = g . f a
dot g f a = (g .) (f a)
dot g f a = ((g .) . f) a
dot g f = (g .) . f짠. a를 소거했습니다. 이제 f도 소거해봅시다. 뭘 어쩔 거냐면: 중위 연산자를 앞으로 보낼 겁니다.
dot g f = (g .) . f
dot g f = (.) (g .) f
dot g = (.) (g .)g도 빼봅시다!
dot g = (.) (g .)
dot g = (.) ((.) g)
dot g = ((.) . (.)) g
dot = ((.) . (.))짠.