io-T와 함께 작업하기에 충분한 fp-T

이것은 fp-ts에 대해 알아야 할 내용에 관한 작은 강좌이다.다시 말하면

Just enough fp-ts to to work with io-ts be 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)
둘 다 대수 유형인데 특히 두 개의 지점RightLeft의 a 를 가지고 있다.첫 번째는 보통 성공을 나타내는 데 쓰이고, 두 번째는 실패를 나타내는 데 쓰인다.우리의 예시에서 t.Errors는Left로 포장한 유형이고 number는Right로 포장한 유형이다.아니면 discriminated union (노조를 차별하는 또 다른 용어) 왼쪽이나 오른쪽일 수 있지만, 동시에 왼쪽이나 오른쪽일 수는 없기 때문이다.
네가 짐작할 수 있는 바와 같이, 이 두 가지 방법의 목적은 모두 실패하거나 성공할 수 있는 조작을 처리하는 것이다.그것은 또 약간의 좋은 기능을 제공했다.
sum type folding📂
어떤 값의 내부에 접근해서 내용을 얻을 수 있지만, 이것은 그 값의 작업 방식이 아니다.
fpts는 가치를 얻기 위해 fold:
declare function fold<E, A, B>(
  onLeft: (e: E) => B,
  onRight: (a: A) => B,
): (e: Either<E, A>) => B
유형 정의가 암시하는 바와 같이, 이것은 우리가 이 두 가지 상황을 처리하기를 바란다.foldArray.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 버전을 보실 수 있습니다.🔍
maping🗺
일단 우리의 도구 테이프에 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라는 단어를 사용하지 않았다.그럴 필요가 없기 때문이다.비록 둘 다 단자이지만, 우리는 그것의 어떤 단자 속성도 사용하지 않았다.우리는 확실히 그것을 편지로 삼았다.편지는 모든 편지의 실례의 일치성을 확보하기 위해 대수 형식으로 정의되어 있다.그 중 하나의 비주얼이 그룹의 비주얼과 다르기를 원하지 않습니다.수조도 편지다.
다시 한 번 이런 용어(단자, 편지, 응용성, 접기 등)를 배우는 것은 필요없다.하지만 흥미가 있다면 아주 유용할 거예요.예를 들어, 만약 당신이 수조가 맵을 정의했다는 것을 알고 있다면, 그것은 편지이기 때문이다.그리고 새로운 대수 형식 (예를 들어 임의의 것) 을 발견했다. 그것도 편지이며, 이 유형의 맵을 어떻게 사용하는지 이미 알고 있다.
됐어, 이렇게.
즐겁고 안전한 인코딩🤓

좋은 웹페이지 즐겨찾기