Monad 패턴이란?
함수형 인터페이스에서 등장하는 디자인 패턴 개념으로,
함수(메서드)에 return값 (Value)을 특정한 타입으로 감싸는 형태의 패턴이다.
모나드 패턴은 두 개의 operator를 정의하는데,
- Unit : 모나드 타입으로 감싸는 형태의 operator
- Bind : 모나드 타입으로 감싸져 있는 것을 다른 함수에 적용한 후 , 다시 모나드로 반환하는 연산자이다.
- Associativity : 연산이 체인될 때 순서와 상관없이 동일한 결과를 보장해야 함.
수학에서의 그 결합법칙이다. 찾아보니 Monad 라는 패턴은 수학에서의 범주론에서 다루는 내용이라
그 내용이 수학에서의 것과 동일하다.
이러한 관점에서 보았을 때
Optional
Optional은 모나드 패턴이다.
Optional<String> unit = Optional.of("Hello"); // Optional.ofNullable("Hello") 도 가능은 함.
Optional<Integer> bind = Optional.of("123")
.flatMap(s -> Optional.of(Integer.parseInt(s))); // Optioanl[123]
Optional<Integer> result1 = Optional.of("123")
.flatMap(s -> Optional.of(Integer.parseInt(s)))
.flatMap(i -> Optional.of(i * 2)); // Optional[246]
Optional<Integer> result2 = Optional.of("123")
.flatMap(s -> Optional.of(Integer.parseInt(s) * 2 )) // Optional[246]
stream이 monad가 아닌이유?
Stream<String> stream1 = Stream.of("123")
.flatMap(s -> Stream.of(s + s));
Stream<String> stream2 = Stream.of("123")
.flatMap(s -> Stream.of(s))
.flatMap(s -> Stream.of(s + s));
// 스트림은 한 번 소비되면 재사용할 수 없기 때문에 연산이 달라질 수 있음.
System.out.println(stream1.equals(stream2)); // false
// 값은 123123으로 같게 나왔지만 두 개의 참조 파이프라인을 살펴보니 달랐다.
// java.util.stream.ReferencePipeline$7@7e9e5f8a
// java.util.stream.ReferencePipeline$7@8bcc55f
➡️ associativity 가 성립하지 않음.
항등함수와 s+s함수가 결합했는데 원래의 값과 다르게 나온 셈이 되는 것이다.
promise가 monad가 아닌이유?
let result1 = Promise.resolve("abc")
.then(s => Promise.resolve(parseInt(s))) // 실패: "abc"는 숫자가 아님
.then(i => Promise.resolve(i * 2))
.catch(error => {
console.log("Result 1 failed with error:", error);
return "Result 1 failed"; // 오류가 발생하면 대체 값 반환
});
let result2 = Promise.resolve("abc")
.then(s => Promise.resolve(parseInt(s) * 2)) // 먼저 두 배로, 여기서 실패
.catch(error => {
console.log("Result 2 failed with error:", error);
return "Result 2 failed"; // 오류가 발생하면 대체 값 반환
});
Promise.all([result1, result2])
.then(values => {
console.log("Result 1:", values[0]); // "Result 1 failed"
console.log("Result 2:", values[1]); // "Result 2 failed"
});
➡️ Promise는 일단 실패가 되는 지점은 서로 동일하다고 볼 수 있으나,
catch 구문에서 실패에 대한 분기처리, 즉 다른 값을 반환 할 수 있는 경우가 존재하기에
associativity를 따른다고 볼 수 없다.
https://en.wikipedia.org/wiki/Monad_(functional_programming)
'연재작 > 프로그래밍 언어' 카테고리의 다른 글
Java - Optional 뽀개기 (1) (0) | 2024.10.11 |
---|---|
Java - Stream 뽀개기 (2) (2) | 2024.10.06 |
Java - Stream 뽀개기 (1) (feat. 함수형 인터페이스) (0) | 2024.10.06 |
Java Collection, Map에 내재되어 있는 수학 (0) | 2024.09.27 |
수학적 철학을 가미한 함수형 프로그래밍 (1) | 2024.08.31 |