Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Higher-Kinded Types #70

Open
youngkyo0504 opened this issue Aug 31, 2024 · 0 comments
Open

Higher-Kinded Types #70

youngkyo0504 opened this issue Aug 31, 2024 · 0 comments

Comments

@youngkyo0504
Copy link
Owner

youngkyo0504 commented Aug 31, 2024


title:
full_path: src/pages/.md

연결리스트와 리스트를 모두 만족할 수 있는 함수를 만들자.

void addUntil<L, T>(L<T> lst, T v, Int len) {
   while (length<T>(lst) < len) {
       add<T>(lst, v)
  }
}

위 함수가 말이 되는가? 적어도 타입스크립트에는 말이 안된다.
제너릭 타입은 그 자체로는 타입이 될 수 없다. 타입도 다 같은 타입이 아닌데 타입의 종류를 나타내는 말이 카인드다.

첫 번째 종류의 타입은 *라는 카인드다.
Int의 카인드는 *이다. String도 *다. 두번째는 * => * 카인드다. 함수의 타입을 생각해보자. 함수의 타입이 이렇다. 또 제너릭 타입도 이에 속한다.

다른 카인드도 있다. Map과 같이 타입 인자 두 개를 받는 타입은 (*, * )= > * 다. 더 복잡한 것도 있다.

class IntContainer<(* => *) L> {
   L<Int> integers;
}

스칼라와 하스켈에서 이를 지원한다.

TS에서 안되나요?

interface Mappable<F> {
  // Type 'F' is not generic. ts(2315)
  readonly map: <A, B>(f: (a: A) => B) => (as: F<A>) => F<B>;
}

이런건 안된디다. 하지만 조금 트릭을 이용하면 Higher kinded polymorphism을 이용할 수 있습니다.

Lightweight higher-kinded polymorphism

To emulate kind polymorphism in TypeScript, we use a technique called defunctionalization,

interface URItoKind<A> {
  'Array': Array<A>;
} // a dictionary for 1-arity types: Array, Set, Tree, Promise, Maybe, Task...
interface URItoKind2<A, B> {
  'Map': Map<A, B>;
} // a dictionary for 2-arity types: Map, Either, Bifunctor...

type URIS = keyof URItoKind<unknown>; // sum type of names of all 1-arity types
type URIS2 = keyof URItoKind2<unknown, unknown>; // sum type of names of all 2-arity types
// and so on, as you desire

type Kind<F extends URIS, A> = URItoKind<A>[F];
type Kind2<F extends URIS2, A, B> = URItoKind2<A, B>[F];
// and so on

이제 Kind를 사용할 수 있다.

type Tree<A> = ...

declare module 'my-lib/path/to/uri-dictionaries' {
  interface URItoKind<A> {
    // 이것은 병합 처리하기위함임
    'Tree': Tree<A>;
  }
}

type Test1 = Kind<'Tree', string>

출처 : Intro to fp-ts, part 1: Higher-Kinded Types | ybogomolov.me

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant