함수식 JavaScript-편지, 쪽지 및 약속
21044 단어 javascriptfunctional
어떤 사람은 a
Promise
가 바로 aMonad
라고 말한다.aPromise
는 aMonad
가 아니라는 말도 있다.그들은 모두 틀렸다...그들은 모두 옳다.이 글을 다 읽으면
Functor
와 Monad
, 그리고 그것들과 Promise
의 유사점과 차이점을 알게 될 것이다.왜 아무도 명세서를 설명할 수 없습니까?
리스트를 이해하는 데 필요한 필수 어휘를 갖추지 못하면 리스트가 무엇인지 설명하기 어렵다.
나는 두 자석 사이의'무슨 일이 일어났는지'를 묘사해 달라는 요청을 받은 리처드 페만의 이 영상을 좋아한다.
전체 영상은 놀랍고 흥분되지만, 공부에 대한 혐오감이 있다면 6:09로 바로 뛸 수 있다.
I can't explain that attraction in terms of anything else that's familiar to you - Richard Feynman @
따라서 aMonad
가 어떤 단어인지 이해하는 데 필요한 몇 가지 절차를 백업해 봅시다.
우리는 편지를 이해할 준비가 되었습니까?
정의: AFunctor
는 Mappable
또는 분류에 있는 대상 사이에 비치는 것을 가리킨다.
네, 괜찮아요.아직.그러나 두려워하지 마십시오. Functors
의 Array
함수를 사용한 적이 있다면, 당신은 이미 익숙해졌습니다. map
[1, 2, 3].map(x => x * 2) //=> [2, 4, 6]
우리가 aFunctor
를 완전히 이해하기 전에 우리는 aMappable
가 무슨 뜻인지 이해해야 하고 aCategory
가 무엇인지도 이해해야 한다.여기서부터 시작합시다.
카테고리, 객체 및 맵(변형)
Acategory
는 하나의 노드(대상)와 상태(함수)로 구성되어 있다.하나의 대상은 숫자, 문자열, URL, 고객, 또는 당신이 원하는 다른 조직 방식일 수 있습니다.(도면의 X, Y 및 Z는 객체입니다.)
Amap
는 함수를 사용하여 객체를 다른 객체로 변환합니다.(f, g, fog는 지도).🔍 구글은 대상 사이의 Amap
를 AMorphism
라고 제시했다.
예: Number Type
방법으로 대상String Type
의 대상을 대상toString()
으로 전환할 수 있다.
// A map of Number -> String
const numberToString = num => num.toString()
maps
를 자신의 대상이나 더 복잡한 대상 유형으로 만들 수 있습니다.
// A map of Number -> Number
const double = num => num * 2
// A map of Array -> Number
const arrayToLength = array => array.length
// A map of URL -> Promise (JSON)
const urlToJson = url =>
fetch(url)
.then(response => response.json())
그래서 한 대상은 숫자나 문자열처럼 간단할 수 있다.대상도 사용자 이름, 사용자 API URL, 사용자 API HTTP 요청, 사용자 API 응답, 사용자 API 응답 JSON 등 더욱 추상적일 수 있다.그런 다음 각 객체 간에 맵 또는 변형을 작성하여 원하는 데이터를 얻을 수 있습니다.
상태의 예:
I can't explain that attraction in terms of anything else that's familiar to you - Richard Feynman @
정의: A
Functor
는 Mappable
또는 분류에 있는 대상 사이에 비치는 것을 가리킨다.네, 괜찮아요.아직.그러나 두려워하지 마십시오.
Functors
의 Array
함수를 사용한 적이 있다면, 당신은 이미 익숙해졌습니다. map
[1, 2, 3].map(x => x * 2) //=> [2, 4, 6]
우리가 aFunctor
를 완전히 이해하기 전에 우리는 aMappable
가 무슨 뜻인지 이해해야 하고 aCategory
가 무엇인지도 이해해야 한다.여기서부터 시작합시다.카테고리, 객체 및 맵(변형)
Acategory
는 하나의 노드(대상)와 상태(함수)로 구성되어 있다.하나의 대상은 숫자, 문자열, URL, 고객, 또는 당신이 원하는 다른 조직 방식일 수 있습니다.(도면의 X, Y 및 Z는 객체입니다.)
Amap
는 함수를 사용하여 객체를 다른 객체로 변환합니다.(f, g, fog는 지도).🔍 구글은 대상 사이의 Amap
를 AMorphism
라고 제시했다.
예: Number Type
방법으로 대상String Type
의 대상을 대상toString()
으로 전환할 수 있다.
// A map of Number -> String
const numberToString = num => num.toString()
maps
를 자신의 대상이나 더 복잡한 대상 유형으로 만들 수 있습니다.
// A map of Number -> Number
const double = num => num * 2
// A map of Array -> Number
const arrayToLength = array => array.length
// A map of URL -> Promise (JSON)
const urlToJson = url =>
fetch(url)
.then(response => response.json())
그래서 한 대상은 숫자나 문자열처럼 간단할 수 있다.대상도 사용자 이름, 사용자 API URL, 사용자 API HTTP 요청, 사용자 API 응답, 사용자 API 응답 JSON 등 더욱 추상적일 수 있다.그런 다음 각 객체 간에 맵 또는 변형을 작성하여 원하는 데이터를 얻을 수 있습니다.
상태의 예:
// A map of Number -> String
const numberToString = num => num.toString()
// A map of Number -> Number
const double = num => num * 2
// A map of Array -> Number
const arrayToLength = array => array.length
// A map of URL -> Promise (JSON)
const urlToJson = url =>
fetch(url)
.then(response => response.json())
Function Composition
는 여러 개map
또는 morphisms
를 조합하여 새로운 maps
를 만드는 방법이라고 제시했다.Function Composition
를 사용하면 Username
에서 User API Response JSON
까지의 지도를 만들 수 있습니다.답장
이제 우리는 Mappable
의 뜻을 깨달았고, 마침내 Functor
가 무엇인지 알게 되었다.Functor
는 Mappable
또는 범주에 있는 객체 간에 매핑할 수 있는 객체입니다.
AnArray
은 Mappable
이기 때문에 aFunctor
입니다.이 예에서 나는 하나Array of Numbers
를 하나Array of Strings
로 변형시켰다.
const numberToString = num => num.toString()
const array = [1, 2, 3]
array.map(numberToString)
//=> ["1", "2", "3"]
주: aFunctor
의 한 특징은 항상 같은 유형Functor
을 유지하는 것이다.Array
가 포함된 Strings
를 Numbers
또는 다른 대상으로 변형시킬 수 있지만 map
는 항상 Array
임을 확보할 수 있다.map
의Array
를 Number
로 전환할 수 없습니다.
우리도 이것Number
의 실용성을 다른 대상으로 확장할 수 있습니다!aMappable
의 이 간단한 예를 예로 들자.
const Thing = value => ({
value
})
만약 우리가 Thing
비추기를 원한다면, Thing
비추기를 할 수 있는 것처럼, 우리가 해야 할 일은 그것에 Array
함수를 주는 것이다.
const Thing = value => ({
value,
map: morphism => Thing(morphism(value))
// ----- -------- -----
// / | \
// always a Thing | value to be morphed
// |
// Morphism passed into map
})
const thing1 = Thing(1) // { value: 1 }
const thing2 = thing1.map(x => x + 1) // { value: 2 }
이것은 map
입니다!사실은 이렇게 간단하다.
🔍 구글은 우리가 만든 Functor
"Thing"
의 이름Functor
을 Identity
이라고 제시했다.
영수증으로 돌아가다
때때로 함수는 포장된 값을 되돌려줍니다.Functor
와 함께 사용하기가 불편할 수 있습니다. 왜냐하면 Functor
를 다른 Functor
에 다시 포장하기 때문입니다.
const getThing = () => Thing(2)
const thing1 = Thing(1)
thing1.map(getThing) //=> Thing (Thing ("Thing 2"))
이 동작은 Array
의 동작과 같습니다.
const doSomething = x => [x, x + 100]
const list = [1, 2, 3]
list.map(doSomething) //=> [[1, 101], [2, 102], [3, 103]]
이곳이 바로 flatMap
에 쓸모가 있는 곳이다.그것은 map
와 유사하지만 다른 것은 변형은 포장 값을 집행해야 한다는 것이다.
const Thing = value => ({
value,
map: morphism => Thing(morphism(value)),
flatMap: morphism => morphism(value)
})
const thing1 = Thing(1) //=> Thing (1)
const thing2 = thing1.flatMap(x => Thing(x + 1)) //=> Thing (2)
많이 좋아진 것 같아!Maybe
에서 Just
로 전환해야 할 수도 있습니다. 예를 들어 도구가 부족할 때Nothing
에서 유용합니다.
import Just from 'mojiscript/type/Just'
import Nothing from 'mojiscript/type/Nothing'
const prop = (prop, obj) =>
prop in obj
? Just(obj[prop])
: Nothing
Just({ name: 'Moji' }).flatMap(x => prop('name', x)) //=> Just ("Moji")
Just({}).flatMap(x => prop('name', x)) //=> Nothing
이 코드는 다음과 같이 축소할 수 있습니다.
const Just = require('mojiscript/type/Just')
const Nothing = require('mojiscript/type/Nothing')
const { fromNullable } = require('mojiscript/type/Maybe')
const prop = prop => obj => fromNullable(obj[prop])
Just({ name: 'Moji' }).flatMap(prop('name')) //=> Just ("Moji")
Just({}).flatMap(prop('name')) //=> Nothing
🔍 구글은 이런 코드 단축은 currying
,partial application
와point-free style
를 통해 가능하다고 제시했다.
아마도 너는 더 많은 것을 기대할 것이다. 그러나 한 명세서에 있어서는 이렇다.쪽지는 비출 수도 있고 평탄하게 비출 수도 있다.
나는 이 점에서 네가 처음에 생각했던 것보다 더 쉬운 여정이라고 생각하기를 바란다.우리는 이미 보도Functors
와 Monads
, 다음Promise
!
언약
만약 그 중 어떤 코드가 익숙해 보인다면 Promise
의 행동은 map
와flatMap
와 유사하기 때문이다.
const double = num => num * 2
const thing1 = Thing(1) //=> Thing (1)
const promise1 = Promise.resolve(1) //=> Promise (1)
thing1.map(double) //=> Thing (2)
promise1.then(double) //=> Promise (2)
thing1.flatMap(x => Thing(double(x))) //=> Thing (2)
promise1.then(x => Promise.resolve(double(x))) //=> Promise (2)
보시다시피 Promise
방법then
은 포장되지 않은 값을 되돌릴 때map
와 유사하고 flatMap
에서 포장할 때Promise
와 유사합니다.이렇게 하면 aPromise
와 aFunctor
와 aMonad
는 비슷하다.
이것도 그것의 차이점이다.
thing1.map(x => Thing(x + 1)) // Thing (Thing (2))
promise1.then(x => Promise.resolve(x + 1)) // Promise (2)
thing1.flatMap(x => x + 1) //=> 2
promise1.then(x => x + 1) //=> Promise (2)
만약 내가 두 번 값을 포장하고 싶다면 (끼워넣기 Arrays
를 고려하거나 되돌아오는 유형을 제어하고 싶다면, 나는 사용할 수 없다. Promise
이렇게 되면 그것은 Functor
법률을 위반했고 Monad
법률도 위반했다.
요약
const numberToString = num => num.toString()
const array = [1, 2, 3]
array.map(numberToString)
//=> ["1", "2", "3"]
const Thing = value => ({
value
})
const Thing = value => ({
value,
map: morphism => Thing(morphism(value))
// ----- -------- -----
// / | \
// always a Thing | value to be morphed
// |
// Morphism passed into map
})
const thing1 = Thing(1) // { value: 1 }
const thing2 = thing1.map(x => x + 1) // { value: 2 }
때때로 함수는 포장된 값을 되돌려줍니다.
Functor
와 함께 사용하기가 불편할 수 있습니다. 왜냐하면 Functor
를 다른 Functor
에 다시 포장하기 때문입니다.const getThing = () => Thing(2)
const thing1 = Thing(1)
thing1.map(getThing) //=> Thing (Thing ("Thing 2"))
이 동작은 Array
의 동작과 같습니다.const doSomething = x => [x, x + 100]
const list = [1, 2, 3]
list.map(doSomething) //=> [[1, 101], [2, 102], [3, 103]]
이곳이 바로 flatMap
에 쓸모가 있는 곳이다.그것은 map
와 유사하지만 다른 것은 변형은 포장 값을 집행해야 한다는 것이다.const Thing = value => ({
value,
map: morphism => Thing(morphism(value)),
flatMap: morphism => morphism(value)
})
const thing1 = Thing(1) //=> Thing (1)
const thing2 = thing1.flatMap(x => Thing(x + 1)) //=> Thing (2)
많이 좋아진 것 같아!Maybe
에서 Just
로 전환해야 할 수도 있습니다. 예를 들어 도구가 부족할 때Nothing
에서 유용합니다.import Just from 'mojiscript/type/Just'
import Nothing from 'mojiscript/type/Nothing'
const prop = (prop, obj) =>
prop in obj
? Just(obj[prop])
: Nothing
Just({ name: 'Moji' }).flatMap(x => prop('name', x)) //=> Just ("Moji")
Just({}).flatMap(x => prop('name', x)) //=> Nothing
이 코드는 다음과 같이 축소할 수 있습니다.const Just = require('mojiscript/type/Just')
const Nothing = require('mojiscript/type/Nothing')
const { fromNullable } = require('mojiscript/type/Maybe')
const prop = prop => obj => fromNullable(obj[prop])
Just({ name: 'Moji' }).flatMap(prop('name')) //=> Just ("Moji")
Just({}).flatMap(prop('name')) //=> Nothing
🔍 구글은 이런 코드 단축은 currying
,partial application
와point-free style
를 통해 가능하다고 제시했다.아마도 너는 더 많은 것을 기대할 것이다. 그러나 한 명세서에 있어서는 이렇다.쪽지는 비출 수도 있고 평탄하게 비출 수도 있다.
나는 이 점에서 네가 처음에 생각했던 것보다 더 쉬운 여정이라고 생각하기를 바란다.우리는 이미 보도
Functors
와 Monads
, 다음Promise
!언약
만약 그 중 어떤 코드가 익숙해 보인다면 Promise
의 행동은 map
와flatMap
와 유사하기 때문이다.
const double = num => num * 2
const thing1 = Thing(1) //=> Thing (1)
const promise1 = Promise.resolve(1) //=> Promise (1)
thing1.map(double) //=> Thing (2)
promise1.then(double) //=> Promise (2)
thing1.flatMap(x => Thing(double(x))) //=> Thing (2)
promise1.then(x => Promise.resolve(double(x))) //=> Promise (2)
보시다시피 Promise
방법then
은 포장되지 않은 값을 되돌릴 때map
와 유사하고 flatMap
에서 포장할 때Promise
와 유사합니다.이렇게 하면 aPromise
와 aFunctor
와 aMonad
는 비슷하다.
이것도 그것의 차이점이다.
thing1.map(x => Thing(x + 1)) // Thing (Thing (2))
promise1.then(x => Promise.resolve(x + 1)) // Promise (2)
thing1.flatMap(x => x + 1) //=> 2
promise1.then(x => x + 1) //=> Promise (2)
만약 내가 두 번 값을 포장하고 싶다면 (끼워넣기 Arrays
를 고려하거나 되돌아오는 유형을 제어하고 싶다면, 나는 사용할 수 없다. Promise
이렇게 되면 그것은 Functor
법률을 위반했고 Monad
법률도 위반했다.
요약
const double = num => num * 2
const thing1 = Thing(1) //=> Thing (1)
const promise1 = Promise.resolve(1) //=> Promise (1)
thing1.map(double) //=> Thing (2)
promise1.then(double) //=> Promise (2)
thing1.flatMap(x => Thing(double(x))) //=> Thing (2)
promise1.then(x => Promise.resolve(double(x))) //=> Promise (2)
thing1.map(x => Thing(x + 1)) // Thing (Thing (2))
promise1.then(x => Promise.resolve(x + 1)) // Promise (2)
thing1.flatMap(x => x + 1) //=> 2
promise1.then(x => x + 1) //=> Promise (2)
Functor
는 Mappable
또는 분류 중의 대상 사이에 비칠 수 있는 것을 가리킨다.Monad
는 AFunctor
와 비슷하지만 분류 간Flat Mappable
이다.flatMap
는 map
와 유사하지만, 맵 함수에 되돌아오는 형식을 포장할 수 있습니다.Functor
과Monad
법률을 위반했지만 비슷한 점이 많다.같지만 다르다.제 글은 JavaScript에 대한 애정을 보여줍니다.FP가 더 필요하시면 여기나 트위터에 팔로우 해주세요!
나의 절친한 친구 존이 이 점을 증명해 줘서 고맙다:)
Reference
이 문제에 관하여(함수식 JavaScript-편지, 쪽지 및 약속), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/joelnet/functional-javascript---functors-monads-and-promises-1pol텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)