viewimage.php?id=3dafdf21f7d335ab67b1d1&no=29bcc427b28b77a16fb3dab004c86b6fdc843afe757eec57bf7102ec3efadaa9fafd0ec78e850e2c4eb89b379b7d885a853a8d48316177892de03b48c8


전부터 궁금했던 게 있었어.


"모든 모나드는 어플리커티브다. 모든 어플리커티브는 펑터다."


그렇다면 비슷한 성격의 타입클래스가 왜 세 개나 있어야 할까?

이에 대한 대답을 어느 정도 알게된 것 같아 정리해본다.


1. 서브클래스가 서브셋을 의미하지 않는다.

저 위의 문장을 클래스 상속 구도로 나타내면


Functor

Applicative: Functor

Monad: Applicative


이렇게 되는데, 가장 유용하고 기능이 많은 것은 모나드임.

즉, 할 수 있는 능력으로 구분하면, 모나드가 가장 강력하고, 어플리커티브는 그 다음, 펑터는 마지막이 되는거지.

서브클래스는 서브셋이 아니라 오히려 수퍼셋에 가깝다. 서브라는 접두사를 공유하지만 포함 관계는 반대.


2. 수학의 함자, 적용성 함자, 단형 함자, 단일체 등등은 몰라도 된다.

정말 알 필요 없음. 내가 공부할 때 곁가지로 자주 빠지는 유형이라 시간대비 성과가 좋지 않은데..

그런 나도 이 쪽 수학은 감히 빠질 생각을 못 하겠더라. 모노이드 하나만 해도 엄청난 양이고 내용도 도대체가 알아들을 수 없는 말들이라서 깔끔하게 접어두기로 했다. cs 전공자라, 그래도 수학 좀 안다고 생각했는데, 완전 깨갱함.

다행히 몰라도 코드 짜는데는 전혀 지장이 없음.


3. 한 눈에 보는 펑터-어플리커티브-모나드


 

Functor

Applicative 

Monad 

map

(a -> b) -> f a -> f b

fmap

<$>

liftM

wrap

a -> f a

없음

pure

return

wrapped map

f (a -> b) -> f a -> f b

없음

<*>

ap

bind

f a -> (a -> f b) -> f b

없음

없음

>>=

flatten

f (f a) -> f a

없음

없음

join


모나드와 어플리커티브는 래퍼 클래스라고 생각하면 됨.

펑터는 그 둘을 포함하는 가장 추상화된 인터페이스라고 보면 되고.

래퍼와 래핑이라는 것은 어떤 컨텍스트에 담는 것을 말하는데, 위의 표에서 a와 f a의 차이를 보면 돼.

a가 일반 값 normal value 이고, f a는 이러한 일반 값을 컨텍스트에 담은 값 fancy value 을 의미한다.


셋의 차이는 다룰 수 있는 함수에서 차이가 나.

펑터는 map만 가능함. 즉 함수 자체는 일반 값에 관한 함수만 받아.

어플리커티브는 펑터의 기능에 추가로, 함수 전체가 래핑된 경우도 처리할 수 있어.

모나드는 어플리커티브의 기능은 물론, 일반 값에서 팬시 값으로 정의된 함수인 경우도 처리할 수 있지.


모나드의 저 말, 일반 값에서 팬시 값으로 정의된 함수가 바로 순수와 비순수를 연결하는 부분이야.

순수성을 위해서 모나드 구조를 도입한 이유를 이해할 수 있는 부분이지.


모두들 재밌는 하스켈 배우자.

람다 후 아크바르!