6. 0. 모나드를 설명한다고?
• 수학적인 모나드를 다루진 않겠음. 나도 사실 잘 모름
• 프로그래밍 관점에서 모나드를 어떻게 사용하는지에 초점을 맞춰서 설명하려 함
7. 0-1. 사전지식
수학에서 함수를 합성한다는 것
f : X -> Y
g : Y -> Z
가 있으면
X -> Z 를 만들 수 있음
g*f
8. 0-1. 사전지식
프로그래밍에서 함수를 합성한다는 것
파일에서 한줄을 읽어서 문자열로 반
환하는 함수 readLine
fi
le -> string
문자열을 띄어쓰기를 기준으로 나누어
리스트로 반환하는 함수 split
string -> list<string>
readLine의 리턴 타입과 split의 인자 타입이 같기 때문에 둘을 합성할 수 있음
파일에서 한 줄을 읽어 띄어쓰기 단위로 문자열을 나누는 함수
split*readLine :
fi
le -> list<string>
+
10. 1. 함수형 프로그래밍?
클로져? 고차함수? 순수함수? 모나드?
• 몇년 전만해도 함수형 프로그래밍이란 단어가 어색했는데 이제는 함수 리터럴, 함수 축약
형, map
fi
lter reduce 연산 등이 당연하게 받아들여짐
11. 1. 함수형 프로그래밍?
클로져? 고차함수? 순수함수? 모나드?
• 몇년 전만해도 함수형 프로그래밍이란 단어가 어색했는데 이제는 함수 리터럴, 함수 축약
형, map
fi
lter reduce 연산 등이 당연하게 받아들여짐
• 그런데 FP가 뭔지 말하라고 하면 딱히 떠오르는 단어가 없음
12. 1. 함수형 프로그래밍?
클로져? 고차함수? 순수함수? 모나드?
• 몇년 전만해도 함수형 프로그래밍이란 단어가 어색했는데 이제는 함수 리터럴, 함수 축약
형, map
fi
lter reduce 연산 등이 당연하게 받아들여짐
• 그런데 FP가 뭔지 말하라고 하면 딱히 떠오르는 단어가 없음
• 그래서 FP의 한 축을 담당하는 모나드와 함수의 합성을 예시와 함께 풀어나가보려 함
13. 1. 함수형 프로그래밍
예시
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
“bearer [id] [pw]”
인증 토큰
ID User
1 KeeHyun
2 ChimChakMan
DB
{
“id” : 2
“name” : “ChimChakMan”
“pw” : “미까따1!”
}
사용자 정보 User
14. 1. 함수형 프로그래밍
구현에 필요한 기능들
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
2. 추출한 ID로 DB에서 사용자 정보 검색
3. PW 검증 후 인증 객체 반환
15. 1. 함수형 프로그래밍
각 기능을 함수로 표현
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
• func extractID : Token -> ID
• func extarctPW : Token -> PW
2. 추출한 ID로 DB에서 사용자 정보 검색
• func
fi
ndUser : ID -> User
3. PW 검증 후 인증 객체 반환
• func verifyPW : (User, PW) -> Auth
이런 함수들을 합성해서
대충 Token을 주면 Auth를 반환하는
함수를 만들어야 함
Token -> Auth
auth := verityPW(
fi
ndUser(extractID(token)),
extractPW(token)
)
16. 1. 함수형 프로그래밍
함수 안에 부작용이 있음
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
• func extractID : Token -> ID (유효하지 않은 토큰 형식으로, 인증 토큰에서 ID를 추출하지 못할 수도 있음)
• func extarctPW : Token -> PW (유효하지 않은 토큰 형식으로, 인증 토큰에서 PW를 추출하지 못할 수도 있음)
2. 추출한 ID로 DB에서 사용자 정보 검색
• func
fi
ndUser : ID -> User (DB에 ID에 해당하는 사용자 정보가 없을 수도 있음)
3. PW 검증 후 인증 객체 반환
• func verifyPW : (User, PW) -> Auth (PW가 틀려서 인증 객체를 생성하지 못할 수도 있음)
17. 1. 함수형 프로그래밍
부작용을 관리하면서 순수 함수들을 합성?
구현하는 함수는 순수 함수로 작성해야 함
=> 함수 내에 부작용이 있으면 안됨
(ex: throw exception)
어떤 타입 T에 대해서
T 값이 있거나 없거나를 나타내는
M<T>가 필요함
18. 1. 함수형 프로그래밍
부작용을 관리하면서 순수 함수들을 합성?
구현하는 함수는 순수 함수로 작성해야 함
=> 함수 내에 부작용이 있으면 안됨
(ex: throw exception)
어떤 타입 T에 대해서
T 값이 있거나 없거나를 나타내는
M<T>가 필요함
Optional<T>
19. 1. 함수형 프로그래밍
리턴 타입을 모두 Optional로 변경
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
• func extractID : Token -> Optional<ID>
• func extarctPW : Token -> Optional<PW>
2. 추출한 ID로 DB에서 사용자 정보 검색
• func
fi
ndUser : ID -> Optional<User>
3. PW 검증 후 인증 객체 반환
• func verifyPW : (User, PW) -> Optional<Auth>
20. 1. 함수형 프로그래밍
함수 작성
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
• func extractID : Token -> Optional<ID>
• func extarctPW : Token -> Optional<PW>
21. 1. 함수형 프로그래밍
함수 작성
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 추출한 ID로 DB에서 사용자 정보 검색
• func
fi
ndUser : ID -> Optional<User>
22. 1. 함수형 프로그래밍
함수 작성
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. PW 검증 후 인증 객체 반환
• func verifyPW : (User, PW) -> Optional<Auth>
23. 1. 함수형 프로그래밍
작성한 순수 함수들을 합성?
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
• func extractID : Token -> Optional<ID>
• func extarctPW : Token -> Optional<PW>
2. 추출한 ID로 DB에서 사용자 정보 검색
• func
fi
ndUser : ID -> Optional<User>
3. PW 검증 후 인증 객체 반환
• func verifyPW : (User, PW) -> Optional<Auth>
근데
extractID : Token -> Optional<ID>
fi
ndUser : ID -> Optional<User>
를 합성시킬 수 없게됨
fi
ndUser*extractID : Token -> Optional<User>
함수를 만들 수 있어야 함
24. 1. 함수형 프로그래밍
Optional을 합성할 수 있어야 함
• 인증 토큰을 받아서 사용자 인증을 하는 프로그램
1. 인증 토큰에서 ID, PW 추출
• func extractID : Token -> Optional<ID>
• func extarctPW : Token -> Optional<PW>
2. 추출한 ID로 DB에서 사용자 정보 검색
• func
fi
ndUser : ID -> Optional<User>
3. PW 검증 후 인증 객체 반환
• func verifyPW : (User, PW) -> Optional<Auth>
M<T>에 대해서 함수 합성을 용이하
게 하는 인터페이스를 제공해야 함
=> Optional<T>
or Maybe<T>
25. 2. Functor
• functor : generic type(F<T>) + lift(or map)
• lift : (f: T -> U) -> (F<T> -> F<U>)
어떤 타입 T, U에 대해서
함수 f: T -> U 가 주어지면
함수 F<T> -> F<U> 를 반환하는 함수
26. 2. Functor
Optional 구현
• lift : (f: T -> U) -> (Optional<T> -> Optional<U>)
• lift(f) : Optional<T> -> Optional<U>
• Optional<T> 에 T값이 없다면 U값이 비어있는 Optional<U> 반환
• Optional<T> 에 T값이 있다면 f(T)의 결과 U값을 담은 Optional<U> 반환
27. 2. Functor
Optional 구현
lift는 함수를 받아 함수를 반환하는 함수
f: T -> U
Unit[U]: U -> Optional[U]
=>
Unit[U]*f: T -> Optional[U]
28. 2. Functor
Optional 구현
Optional 때문에 합성을 할 수 없었던 문제
extractID : Token -> Optional<ID>
fi
ndUser : ID -> Optional<User>
를 합성시킬 수 없게됨
fi
ndUser*extractID : Token ->
Optional<User>
함수를 만들 수 있어야 함
fi
ndUser를 lift 시키고 extractID와 합성하면?
lift(
fi
ndUser) : Optional<ID> ->
Optional<Optional<User>>
lift(
fi
ndUser)*extractID : Token ->
Optional<Optional<User>>
합성할 수는 있지만 Optional이 두번 적용되어
있어 사용하기 힘듦
lift를 해도 Optional이 한번만 적용되어있을 순 없을까??
해서 필요한 것이 Monad
29. 3. Monad
• monad : functor + unit +
fl
at
• unit : T -> M<T>
어떤 타입 T에 대해서
T를 M<T>로 변환하는 함수
•
fl
at : M<M<T>> -> M<T>
어떤 타입 T에 대해서
M<M<T>>를 M<T>로 변환하는 함수
타입 T에 대해서 어떠한 개념을
적용시키는 함수
어떠한 개념이 두번 적용된 것을
한 겹 벗기는 함수
31. 3. Monad
Optional 구현
• unit : T -> Optional<T>
• T가 nil이라면 값이 비어있는 Optional<T> 반환
• T가 nil이 아니라면 T값을 담은 Optional<T> 반환
32. 3. Monad
Optional 구현
•
fl
at : Optional<Optional<T>> -> Optional<T>
• Optional<Optional<T>> 가 비어있다면 비어있는 Optional<T> 반환
• Optional<Optional<T>> 가 비어있지 않다면 그대로 Optional<T> 반환
33. 3. Monad
fl
at의 활용
Optional이 2번 적용되어 사용하기 힘들었던 문제
lift(
fi
ndUser)*extractID : Token -> Optional<Optional<User>>
Optional이 2번 적용된 결과에
fl
at을 적용
lift(
fi
ndUser)*extractID : Token -> Optional<Optional<User>>
fl
at : Optional<Optional<User>> -> Optional<User>
fl
at*lift(
fi
ndUser)*extractID : Token -> Optional<User>
=>
fl
atlift(or
fl
atMap)
34. 3. Monad
fl
atlift
fl
atlift를 통해
fi
ndUser와 extractID를 합성할 수 있게됨!
fl
at*lift(
fi
ndUser)*extractID : Token -> Optional<User>
or
fl
atlift(
fi
ndUser)*extractID : Token -> Optional<User>
35. 3. Monad
인자가 2개인 함수는 어떻게 lift?
이제 인증 토큰을 인증 객체로 바꾸는 함수를 만드는데 남은 것
fl
atlift(
fi
ndUser)*extractID : Token -> Optional<User>
extractPW : Token -> Optional<PW>
+
verifyPW : (User, PW) -> Optional<Auth>
어떤 타입 T, U, V 에 대해서
f: (T, U) -> Optional<V> 가 주어지면
(Optional<T>, Optional<U>) -> Optional<V>를 반환하는 함수