io-T와 함께 작업하기에 충분한 fp-T
Just enough fp-ts to
to work with io-tsbe dangerous
io-ts
지금 왜 그래?
우선 이 두 개의 라이브러리와 그것들이 무엇인지 소개합시다.
fp ts
Typed functional programming in TypeScript
... a library containing implementations of common algebraic types in TypeScript
이것은 매우 명백한 것 같다.그래, 아닐 수도 있어 . 하지만 이것은 실천에서 결코 중요하지 않다.
io ts
Runtime type system for IO decoding/encoding
뭐?!
iots는 안전한 인코딩/디코딩을 제공합니다.우리는 이것이 올바른 방식
JSON.parse
과 유형의 두뇌라고 말할 수 있다.더 많은 정보를 얻기 위해 도서관 문서를 보십시오.algebraic types
그런데 왜요?
iots는 의 일부이고 fpts는 메인 라이브러리입니다.따라서 IOts는 fp-ts를 자연스럽게 잘 활용했다.
만약 당신이 FP에 익숙하다면, 당신은 왜 아직도 책을 읽고 있습니까?혹은 너도 이 문장을 완성하고 개선 건의를 제기할 수 있다😅
다른 한편, FP에 익숙하지 않고 ecosystem of typed functional programming (FP) in TypeScript보면 무섭게 보일 수도 있고 처리해야 할 정보가 많을 것 같다.특히 이상한 단어들.이것은 좀 무섭다. 나는 너의 견해에 동의한다.하지만 IOts를 사용하기 위해서는 라이브러리의 아주 작은 부분만 필요합니다.그 외에 제 조언은 학습에 사용되는 라이브러리의 다른 API와 마찬가지로 다루는 것입니다.FP 모드를 적극 제창하지 않고 정말 배울 만하고 함께 일하는 것도 즐겁다고 말하고 싶습니다.
fp-ts website
오른쪽이거나 왼쪽이거나
iots로 형식을 디코딩할 때, 우리가 본 이상한 새로운 상황은 type
Either<t.Errors, T>
의 값을 되돌려주는 것이다. (그 중 T
은 우리가 디코딩하고자 하는 형식이다.import * as t from 'io-ts'
const result: Either<t.Errors, number> = t.number.decode(123)
둘 다 대수 유형인데 특히 두 개의 지점Right
과 Left
의 a
를 가지고 있다.첫 번째는 보통 성공을 나타내는 데 쓰이고, 두 번째는 실패를 나타내는 데 쓰인다.우리의 예시에서 t.Errors
는Left로 포장한 유형이고 number
는Right로 포장한 유형이다.아니면 discriminated union (노조를 차별하는 또 다른 용어) 왼쪽이나 오른쪽일 수 있지만, 동시에 왼쪽이나 오른쪽일 수는 없기 때문이다.네가 짐작할 수 있는 바와 같이, 이 두 가지 방법의 목적은 모두 실패하거나 성공할 수 있는 조작을 처리하는 것이다.그것은 또 약간의 좋은 기능을 제공했다.
sum type
fold
ing📂어떤 값의 내부에 접근해서 내용을 얻을 수 있지만, 이것은 그 값의 작업 방식이 아니다.
fpts는 가치를 얻기 위해
fold
:declare function fold<E, A, B>(
onLeft: (e: E) => B,
onRight: (a: A) => B,
): (e: Either<E, A>) => B
유형 정의가 암시하는 바와 같이, 이것은 우리가 이 두 가지 상황을 처리하기를 바란다.fold
와 Array.reduce
사이에 비슷한 점이 있는데 이것도 포장 유형(Array<A>
을 단일치(B
로 전환하는 방법이다.declare function reduce<A, B>(
f: (acc: B, current: A) => B,
initialValue: B,
): (arr: Array<A>) => B
주: 한 쪽의 접은 서명과 일치하도록 서명of Array.reduce
을 변경했습니다.우리는 주로
fold
를 소비의 방식으로 사용할 것이다.예를 들어 IO ts를 사용하여 API 응답을 디코딩하면 성공적인 작업 ((onRight
이나 실패한 작업을 보내고 Honeybadger에 오류 onLeft
를 보고합니다.fpts가 정의한 대부분의 대수 유형이 자신만의
fold
버전을 보실 수 있습니다.🔍map
ing🗺일단 우리의 도구 테이프에
fold
가 있으면, 우리가 그것을 사용하려고 할 때마다, 우리는 그 중에서 가치를 추출하려고 시도할 수 있다.만약 내가 너에게 말한다면, 너는 이렇게 할 필요가 없니?
Array.map
처럼 map
라는 정의도 있다.// Array's map
declare function map<A, B>(f: (a: A) => B): (arr: Array<A>) => Array<B>
// Either's map
declare function map<A, B>(f: (a: A) => B): <E>(e: Either<E, A>) => Either<E, B>
주의: 그 중 하나와 일치하도록 Array.map
서명을 변경했습니다.보시다시피, 그 내용에 함수를 적용해서 정확한 값을 변환할 수 있습니다.만약 우리의 가치가 마침 왼쪽이라면, 그것은 변하지 않을 것이다.우리는 포장 가치를 계속 즐겁게 사용할 수 있다.
fold
ing이 필요 없다.당신이 묻는 왼쪽 값을 바꾸는 것이 어떻습니까?
mapLeft
구조하러 왔는데, 이번에는 변하지 않는 것이 옳았다.declare function mapLeft<E, G>(
f: (e: E) => G,
): <A>(fa: Either<E, A>) => Either<G, A>
패브릭 Eithers👷♀
우리가 가장 알 필요가 없는 것은 가치관을 어떻게 구축하는가이다.
import {left, right, Either} from 'fp-ts/lib/Either'
declare function left<E = never, A = never>(e: E): Either<E, A>
declare function right<E = never, A = never>(a: A): Either<E, A>
const aRight: Either<never, number> = right(123)
const aLeft: Either<string, never> = left('some error message')
엄밀히 말하면, 이것은 우리가 fp-ts로 io-ts를 처리하는 데 필요한 모든 기능이지만, 우리는 또한 그것이 제공하는 일부 실용 프로그램을 사용하여 함수를 처리할 것이다.이것은 어쨌든 FP 도서관이야, 그렇지?
담뱃대🚿
이것은 fp-ts에서 함수를 조합하는 방법입니다. 함수 목록을 통해 다음 함수를 이전 함수의 결과로 호출합니다.
예를 들면 다음과 같습니다.
export const decodeWith = <A>(decoder: Decoder<unknown, A>) => (
response: unknown,
) =>
mapLeft((errors) => ({tag: 'decoding', errors} as const))(
humanizeErrors(decoder.decode(response)),
)
우리는 잠재적인 오류를 인성화시키고 왼쪽을 다른 유형으로 비추는 응답을 디코딩합니다.파이프가 있으면 이렇게 보입니다.
import { pipe } from 'fp-ts/lib/pipeable';
export const decodeWith = <A>(decoder: Decoder<unknown, A>) => (
response: unknown,
) =>
pipe(
response,
decoder.decode,
humanizeErrors,
mapLeft((errors) => ({tag: 'decoding', errors} as const)),
)
이제 코드는 설명처럼 읽힙니다.decode a response, humanize the potential errors and then map the left to another type.
pipe의 장점 중 하나는 JS에 로그인할 준비가 되어 있다는 것이다.불행하게도 TC39의 작업 속도를 보면 몇 년이 걸릴 수 있습니다.
-import { pipe } from 'fp-ts/lib/pipeable';
-
export const decodeWith = <A>(decoder: Decoder<unknown, A>) => (
response: unknown,
) =>
- pipe(
- response,
- decoder.decode,
- humanizeErrors,
- mapLeft((errors) => ({tag: 'decoding', errors} as const)),
- )
+ response
+ |> decoder.decode
+ |> humanizeErrors
+ |> mapLeft(errors => ({ tag: 'decoding', errors } as const))
유동✉️
flow
는 오른쪽에서 왼쪽으로 함수 조합이다.파이프와 매우 유사하지만, 값을 첫 번째 인자로 하지 않고 함수로 되돌려줍니다.-import { pipe } from 'fp-ts/lib/pipeable';
+import { flow } from 'fp-ts/lib/function';
-export const decodeWith = <A>(decoder: Decoder<unknown, A>) => (
- response: unknown,
-) =>
- pipe(
+export const decodeWith = <A>(decoder: Decoder<unknown, A>) =>
+ flow(
- response,
decoder.decode,
humanizeErrors,
mapLeft((errors) => ({tag: 'decoding', errors} as const)),
)
the pipeline operator proposal 이렇게 하지만 더 많아
IO ts를 사용하는 데 있어서 이것은 우리가 알아야 할 fp ts에 대한 모든 정보이다. (적어도 현재는 이렇다.)만약 네가 이미 싫증이 났다면, 계속 읽을 필요가 없다.
비록 우리는 fpts(그리고 생태계)를 다른 많은 일에 사용할 수 있지만, 이것은 좋은 시작이다.모든 IO 내용 (API 응답이라고도 함) 을 디코딩함으로써, 우리는 의외의 실행 시 행동과 오류를 삭제할 것을 보장합니다. 왜냐하면 컴파일러 a
JSON.parse
가 실제적으로 돌아오지 않는 내용을 되돌려준다고 약속했기 때문입니다.그 가치를 보고 FP에 대한 더 많은 정보를 알고 싶으면 FP ts 문서의 와 부분을 보십시오.무엇보다 질문을 꼭 하고 FP를 배우고 있는 다른 사람을 찾아야 한다.
Core Concepts
M 자 없어요?🌯
왠지 모르게 나는 FP를 쓸 때 Monad라는 단어를 사용하지 않았다.그럴 필요가 없기 때문이다.비록 둘 다 단자이지만, 우리는 그것의 어떤 단자 속성도 사용하지 않았다.우리는 확실히 그것을 편지로 삼았다.편지는 모든 편지의 실례의 일치성을 확보하기 위해 대수 형식으로 정의되어 있다.그 중 하나의 비주얼이 그룹의 비주얼과 다르기를 원하지 않습니다.수조도 편지다.
다시 한 번 이런 용어(단자, 편지, 응용성, 접기 등)를 배우는 것은 필요없다.하지만 흥미가 있다면 아주 유용할 거예요.예를 들어, 만약 당신이 수조가 맵을 정의했다는 것을 알고 있다면, 그것은 편지이기 때문이다.그리고 새로운 대수 형식 (예를 들어 임의의 것) 을 발견했다. 그것도 편지이며, 이 유형의 맵을 어떻게 사용하는지 이미 알고 있다.
됐어, 이렇게.
즐겁고 안전한 인코딩🤓
Reference
이 문제에 관하여(io-T와 함께 작업하기에 충분한 fp-T), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/gillchristian/enough-fp-ts-to-work-with-io-ts-20ip텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)