지난 글에 haskell에서 정의한 functor는 아래와 같다고 하였다.
fmap :: (a -> b) -> fa -> fb 해석을 하면
1. a를 받아 b를 리턴하는 함수를 인자로 받는다.
2. a가 담긴 functor를 받아 b가 담긴 functor를 리턴한다.
자 일단 배열은 functor이고, 위와 같이 작성해보면,
1. a를 받아 b를 리턴하는 함수를 인자로 받는다.
2. a가 담긴 배열을 받아 b가 담긴 배열을 리턴한다.
이제야 배열이 functor라는 것을 순환 없이 이해 할 수 있게 되었다. 자 그러면 배열처럼 값을 순환해주는 functor를 작성해보도록 하자.
function Stream(value) {
this.value = value?.[Symbol.iterator] ? value : []
this.map = function (cb) {
const res = []
for(const v of this.value) {
res.push(cb(v))
}
return new Stream(res)
}
}
new Stream([1, 2, 3]).map(x => x)
// ~ [1, 2, 3]
new Stream([1, 2, 3]).map(x => x).map(x => x * 2)
// ~ [2, 4, 6]
이름을 Stream으로 작성해보았다.
배열의 map과 달리 나의 경우에는 Symbol.iterator를 기준으로 삼았기에 아래와 같은 작업도 가능하게 되었다.
new Stream('123').map(x => x)
// ~ [1, 2, 3]
new Stream(null).map(x => x)
// ~ []
new Stream().map(x => x)
// ~ []
이렇게 하면 여러 데이터 타입을 배열로 사용할 수 있게 되지만, 원래의 데이터 타입이 무엇이였는지에 대한 정보는 잃어버리게 된다.
댓글
댓글 쓰기