fp-ts 시작하기: Ord

12994 단어 functionaltypescript
이전 블로그 게시물에서 우리는 평등의 개념을 다루었습니다. 이 블로그 게시물에서 우리는 순서의 개념을 다룰 것입니다.

전체 순서를 허용하는 유형을 포함하기 위한 유형 클래스Ord는 다음과 같이 선언됩니다.

import { Eq } from 'fp-ts/Eq'

type Ordering = -1 | 0 | 1

interface Ord<A> extends Eq<A> {
  readonly compare: (x: A, y: A) => Ordering
}


우리는 말한다
  • x < y compare(x, y)-1와 같은 경우에만
  • xycompare(x, y)와 같을 때만 0와 같습니다.
  • x > y compare(x, y)1와 같은 경우에만

  • 결과적으로 우리는 x <= y if and only if compare(x, y) <= 0라고 말할 수 있습니다.

    예를 들어 다음은 Ord 유형에 대한 number 인스턴스입니다.

    const ordNumber: Ord<number> = {
      equals: (x, y) => x === y,
      compare: (x, y) => (x < y ? -1 : x > y ? 1 : 0)
    }
    


    인스턴스는 다음 법률을 충족해야 합니다.

  • 반사성: compare(x, x) === 0 , 모두를 위해 x A

  • 비대칭: compare(x, y) <= 0compare(y, x) <= 0 이면 xy , 모두에 대해 x , y in A

  • 전이성: if compare(x, y) <= 0 and compare(y, z) <= 0 then compare(x, z) <= 0 , for all x , y , z in A

  • 또한 compareEqequals를 준수해야 합니다.
    compare(x, y) === 0 if and only if equals(x, y) === true , for all x , y in A
    메모. equalscompare에서 다음과 같은 방식으로 파생될 수 있습니다.

    equals: (x, y) => compare(x, y) === 0
    


    실제로 모듈fp-ts/OrdfromCompare 함수를 지정하여 Ord 인스턴스를 정의할 수 있는 편리한compare 도우미를 내보냅니다.

    import { Ord, fromCompare } from 'fp-ts/Ord'
    
    const ordNumber: Ord<number> = fromCompare((x, y) => (x < y ? -1 : x > y ? 1 : 0))
    


    그런 다음 프로그래머는 다음과 같은 방식으로 함수min(최소 두 값을 취함)를 정의할 수 있습니다.

    function min<A>(O: Ord<A>): (x: A, y: A) => A {
      return (x, y) => (O.compare(x, y) === 1 ? y : x)
    }
    
    min(ordNumber)(2, 1) // 1
    


    숫자에 대해 이야기할 때 전체성이 분명해 보일 수 있지만(예: x <= y 또는 y <= x ), 항상 그런 것은 아닙니다. 좀 더 복잡한 유형을 고려하자

    type User = {
      name: string
      age: number
    }
    

    Ord<User>를 어떻게 정의할 수 있습니까?

    글쎄, 그것은 정말로 의존하지만 가능한 선택은 사용자를 정렬하는 것입니다age
    const byAge: Ord<User> = fromCompare((x, y) => ordNumber.compare(x.age, y.age))
    

    contramap를 사용하여 일부 상용구를 피할 수 있습니다. Ord에 대한 A의 인스턴스와 B에서 A까지의 함수가 주어지면 Ord에 대한 B의 인스턴스를 파생할 수 있습니다.

    import { contramap } from 'fp-ts/Ord'
    
    const byAge: Ord<User> = contramap((user: User) => user.age)(ordNumber)
    


    이제 min를 사용하여 두 사용자 중 어린 사용자를 선택할 수 있습니다.

    const getYounger = min(byAge)
    
    getYounger({ name: 'Guido', age: 48 }, { name: 'Giulio', age: 45 }) // { name: 'Giulio', age: 45 }
    


    대신 더 오래된 것을 선택하고 싶다면 어떻게 하시겠습니까? 우리는 "순서를 뒤집거나"더 기술적으로 말하자면 이중 순서를 얻어야 합니다.

    다행히도 이를 위해 내보낸 또 다른 결합기가 있습니다.

    import { getDualOrd } from 'fp-ts/Ord'
    
    function max<A>(O: Ord<A>): (x: A, y: A) => A {
      return min(getDualOrd(O))
    }
    
    const getOlder = max(byAge)
    
    getOlder({ name: 'Guido', age: 48 }, { name: 'Giulio', age: 45 }) // { name: 'Guido', age: 48 }
    


    다음 게시물

    좋은 웹페이지 즐겨찾기