하스켈의 모든 함수는 인자를 1개씩만 받는다. (우리가 05번 노트에서 배울 람다계산법도 그러하다)
그러면 인자를 두개 받는 함수는 그럼 어떻게? 예를 들면 수학에서 $f(x,y)$ 이런 건 어떻게 표현?
나는 저것도 인자를 1개 받는다고 취급하겠다. 무슨 이야기냐 하면 ...
$(x,y)$라는 순서쌍을 하나 만들어서 한개의 순서쌍을 괄호 없이 $f$로 호출
p :: (Int,Int) -- 수학에서는 Int x Int
p = (2,3)
-- add도 인자를 1개 받는데 그 받는 인자의 타입이 마침 순서쌍일 뿐 ...
addU :: (Int,Int) -> Int
addU (x,y) = x + y
-- addU p = case p of (x,y) -> x + y
addU p
5
그럼 이건 뭔데??? 아 그거는 ...
addC
는 Int
값을 하나만 받는 함수야. 그리고 Int -> Int
함수값을 돌려줘!
(뭐 필요하면 그 리턴값에 또 Int
값 하나를 더 줘서 한번 더 호출해 보던가 말던가 그건 니가 알아서 하고)
addC :: Int -> Int -> Int
addC x y = x + y
-- addC x = f where f y = x + y
addC 2 3
5
a2 = addC 2
:type a2
a2 3
a2 100
5
102
이런 사실상 같은 일을 하는데 타입이 조금씩 다른 이런 함수들을 생각해 볼 수 있다.
addU :: (Int,Int) -> Int
addU (x,y) = x + y
addC :: Int -> Int -> Int
addC x y = x + y
addU가 굉장히 복잡한 기능이고 외부라이브러리는 addU 스타일로 되어 있는데, 우리 프로젝트는 addC같은 스타일로 작업하고 있는 경우에 ...
addC를 새로 정의하지 않고 addU를 addC의 타입으로 변환해주는 고차함수를 curry
라고 합니다.
반대 상황의 경우에 addC를 addU의 타입으로 변환해주는 고차함수를 uncurry
라고 합니다.
:type addU
addU (3,5)
addC' = curry addU
:type addC'
addC' 3 5
8
8
:type addC
addC 3 5
addU' = uncurry addC
:type addU'
addU' (3,5)
8
8
:type curry
:type uncurry
curry :: ((a, b) -> c) -> (a -> b -> c)
curry fu = fc
where fc x y = fu (x,y) f
addU (5,3)
(curry addU) 5 3
8
8
uncurry :: (a -> b -> c) -> ((a, b) -> c)
uncurry fc = fu
where fu (x,y) = fc x y -- fc를 이용해서 작성
addC 5 3
(uncurry addC) (5,3)
8
8