[함수형 프로그래밍] Functor와 Monad
2020. 4. 9. 16:10ㆍiOS
Functor
- map 함수를 지원하는 컨테이너 타입(map을 구현하는 타입)
- Context + value + map transform = Functor
- Context → 어떤 value 가 처해 있는 상태
- Collection, Optional 등의 값을 가지는 container
- 포함하는 value가 generic으로 표현 되어야 함
- Value → Context에 넣어지는 실제 내용
- Context가 generic으로 표현되기 때문에 어떤 타입의 value라도 사용 가능
- Transform → 어떤 값 T를 U로 변환해 주는 function
- T와 U는 같은 타입이여도 상관 없음
- Context → 어떤 value 가 처해 있는 상태
- 컨테이너에서 값을 뺀 후, 값에 특정 함수를 적용해 타입과 값을 변경하고, 다시 값을 컨테이너에 넣는 것
- Array 타입은 map 함수를 지원하기 때문에 Functor 이다.
let numbser: [Int] = [1, 2, 3] var doubledNumbers: [Int] = [] for number in numbers { doubledNumbers.append(number * 2) } print(doubledNumbers) // [2, 4, 6]
map
- map을 사용하면 array의 요소를 변환하는 작업 의도를 더 명확하게 표현할 수 있다.
- '어떻게'가 아닌 '무엇을 달성하려는지'를 더 잘 표현Optional
let numbers = [1, 2, 3] let doubledNumbers = numbers.map { $0 * 2 } print(doubledNumbers) // [2, 4, 6]
- Optional도 map이 적용 가능한 컨테이너 타입
let number: Int? = 123 // == Optional(123) let transNumber = number.map { $0 * 2 } .map { $0 % 2 == 0 } print(transNumber) // Optional(true)
- Optional.map은 nil을 대신 처리해준다.
- 원래 값이 nil이라면 map을 적용해도 nil을 반환
let number: Int? = nil let transNumber = number.map { $0 * 2 } .map { $0 % 2 == 0 } print(transNumber) // nil
Result
- 몇몇 프로그래밍 언어에서 Either라고 알려진 타입의 구현
- case Error 연관 값은 제네릭 대신 NSError 타입으로 연산의 결과를 보고하는데 사용
- 개념적으로 Result는 값이 있을 수도 있고, 없을 수도 있는 임의의 타입의 값을 포장하는 Optional과 유사
- 왜 그 값이 없는지도 알려줌 → NSError
extension Result { func map<U>(f: T -> U) -> Result<U> { switch self { case let .Value(value): return Result<U>.Value(f(value)) case let .Error(error): return Result<U>.Error(error) } } }
- 위의 예제는 Result.map을 구현한 코드
- f는 타입 T의 값을 받고 타입 U를 반환한다
- 값이 있으면 value를 파라미터로 f를 호출, 값이 없다면 error를 반환
Dictionary, Clourse 같은 타입도 Functor이라고 할 수 있다.
Monad
- 포장된 값을 반환하는 함수에 포장된 값을 적용한다
- 값이 있을 수도 있고 없을 수도 있는 상태를 포장하는 타입(Swift에서는 Optional)
- Functor의 한 종류
- flatMap 연산이 가능한 모든 것을을 모나드라고 볼 수 있다
// map
func mapEx<U>(_ transform: (Wrapped)->U) -> U?{
switch self {
case .some(let value):
return transform(value)
case .none:
return .none
}
}
// flatMap
func flatMapEx<U>(_ transform: (Wrapped) ->U?) -> U?{
switch self {
case .some(let value):
return transform(value)
case .none:
return .none
}
}
- transform 메소드 반환 타입이 다르다
let stringNumber: String? = "5"
let mapResult = stringNumber.mapEx {Int($0)} // Optional<Optional>
let flatMapResult = stringNumber.flatMapEx {Int($0)} // Optional
'iOS' 카테고리의 다른 글
[함수형 프로그래밍] Maybe & Either (0) | 2020.04.10 |
---|---|
[함수형 프로그래밍] 일급 함수 (0) | 2020.04.04 |
[함수형 프로그래밍] 순수함수 & 익명함수 & 고차함수 (0) | 2020.04.03 |