Monad에서 이야기 하면서 box에서 값을 꺼내고, 다른 box에서 사상,값을 꺼내서 적용할 수 있게 하는 구조가 Applicative Functor라 했다.
Monad가 flatMap으로 대표 된다면, Applicative Functor는 map2라는 것으로 대표된다.
이들은 각각 장단점이 있으며 그 차이점들을 찾아가 보자.
Applicative Functor trait
Applicative Functor trait 정의
Applicative functor는 다음의 함수 unit 항등함수와 map2의 함수를 가진다.
또한 map함수를 map2와 unit으로 구현함으로써 Applicative functor 또한 Functor의 하위 구조가 될 수 있음을 알 수 있다.
따라서 Applicative functor도 Functor의 성질인 구조적 보존의 법칙을 지켜야 한다.
Applicative Functor trait의 또다른 표현
Applicative Functor는 map2를 apply(적용하다) 함수를 기본수단하여 구현 할 수 있다.
모든 Moand는 Functor 이며 Applicative Functor라 했다. 그럼 flatMap으로 map과 map2를 구현 할 수 있다.
Monad와 Applicative Functor의 차이점
연산의 관여성
monad는 구조를 이전의 funtion effect의 결과에 따라 동적으로 선택할 수 있다. 즉 이전의 계산결과가 그다음의 계산 결과에 영향을 미친다.
반면 Applicative는 두 연산이 서로 상관없이 독립적으로 실행되며 그냥 function effect를 차례로 적용할 뿐이다.
rs01 의 flatMap에서는 users 정보에 결과가 있을 경우에만 이후의 작업인 AF.map2 가 실행된다.
flatMap의 결과 조차 없다면 이후 작업은 가지도 않는다.
monad는 두 function effect간에 호환, 연관되어 다음의 작업을 해야만 할때, 처음의 function effect에 따라 동적으로 다음의 function effect를 할 수 있는 장점이 있다.
반면 rs03의 map2는 lectures 조회와, dates 조회가 각각 독립적으로 실행이 된다.
즉 lectures 의 실행은 dates의 실행에 아무런 영향을 주지 않는다.
위의 이런 Applicative Functor의 특징은 validation 에 적합한 예를 가진다.
web service 에서 사용자가 입력한 form 정보의 field에 따른 모든 검증결과를 담을 수 있기 때문이다.
반면 Monad인 flatMap으로 한다면 1번째 검증이 성공해야만 다음 검증을 실행할 수 있다.
function effect
Option,List,Map 등 형식생성자의 자료구조는 값을 포함하는 것 이외의 기능를 추가로 가진다. 이런 추가적 기능을 Function effect라 한다.
compose
Applicative functor는 F[G[_]] 처럼 합성을 추상화 시킬 수 있지만,Monad는 그렇게 할 수 없고 Moand마다의 특징에 맞는 만들어야 한다.
Applicative Functor law
항등법칙
결합법칙
우선 monoid 의 이진연산 처럼
op(a, op(b,c)) == op(op(a,b),c) 처럼 알아 보기 쉽게 하기 위해 map2와 unit을 기본으로한 추가적 함수를 작성해서 검증해보자.
그리고 다음처럼 해보면 쉽게 보인다.
곱의 자연성 법칙
map2의 parameter 인자의 값들을 결합하기 전에 변환을 해서 적용할때와 결합한 후에 적용할경우와 결과가 같아야 한다는 것이다.
위의 usePhone01은 User와 MobilePhone class를 알고 있어야 한다.
하지만 usePhone02처럼 User 와 MobilePhone에서 조회 한 결과를 인자로 넣으므로써 userPhone02함수는 User와 MobilePhone class를 몰라도 적용이 된다.
이는 상황에 따라 좀더 맞게 적용하면 되는 것으로 위처럼 값들을 결합하기 전에 변환을 해서 적용할때와 결합한 후에 적용할 경우와의 결과가 같아야 함을 의미한다.
이를 증명하기위해 다음의 함수 2개를 받아서 각각의 함수 input의 곱을 받아 output의 곱을 반환하는 함수를 작성한다.