Как напечатать этот функтор Maybe? - PullRequest
0 голосов
/ 26 мая 2020

Это моя попытка ввести функтор Maybe (реализация является адаптацией от доктора Фрисби):

interface Maybe<T> {
  isNothing: () => boolean;
  map: <S>(fn: (x: T) => S) => T extends null | undefined ?  Maybe<S> : Maybe<T>;
  join: <S>(fn: (x: T) => S) => T | S;
  chain: <S>(fn: (x: T) => S) => T | S;
}

function Maybe<T>(x): Maybe<T> {
  const instance = {};

  const isNothing = () => x === null || x === undefined;
  const map = <S>(fn: (x: T) => S): T extends null | undefined ? Maybe<S> : Maybe<T> => isNothing() ? Maybe<T>(x) : Maybe<S>(fn(x));
  const join = () => isNothing() ? Maybe<T>(x) : x;
  const chain = <S>(fn: (x: T) => S) => (instance as Maybe<T>).map(fn).join();

  return Object.assign(instance, { isNothing, map, join, chain });
}

На карте я получаю эту ошибку:

Type 'Maybe<T> | Maybe<S>' is not assignable to type 'T extends null ? Maybe<S> : Maybe<T>'.
  Type 'Maybe<T>' is not assignable to type 'T extends null ? Maybe<S> : Maybe<T>'.

В соединении я получаю следующее:

This expression is not callable.
  Each member of the union type '(<S>(fn: (x: T) => S) => T | S) | (<S>(fn: (x: S) => S) => S | S)' has signatures, but none of those signatures are compatible with each other.

Помогите мне разобраться в этих ошибках и указать правильное направление.

1 Ответ

0 голосов
/ 14 июля 2020

Это все неправильно:

map: <S>(fn: (x: T) => S) => T extends null | undefined ?  Maybe<S> : Maybe<T>;

Я думаю, вы имели в виду

map: <S>(fn: (x: T) => S) => T extends null | undefined ?  Maybe<T> : Maybe<S>;

, потому что весь смысл, возможно, заключается в том, чтобы остановить вычисления, если T расширяет null | неопределенный. в любом случае, что вы делаете, это просите машинописный текст вычислить, является ли экземпляр «возможно» ничем перед выполнением программы. Смысл использования «может быть» не в этом, и это не дает никакой пользы. Я бы рекомендовал написать тип Maybe, который выражает наличие типа A или наличие нулевого типа отдельно от вашего типа для map

Пример реализации:

type Some<A> = { _tag: 'some', val: A };
type None = { _tag: 'none' };
// this is the lazy way to express T extends null | undefined ?  Maybe<T> : Maybe<S>;
// we dont care about computing it while writing a program, only that the program handles
// the none type
export type Maybe<A> = Some<A> | None;

const Some = <A>(a): Maybe<A> => ({ _tag: 'some', val: a });
const None = <A = unknown>(): Maybe<A> => ({ _tag: 'none' });

const isNone = <A = unknown>(fa: Maybe<A>) => fa._tag === 'none';

// (f) => (fa) => (fb)
const map = <A, B>(f: (a: A) => B, fa: Maybe<A>): Maybe<B> =>
    fa._tag === 'none' ? None() : Some(f(fa.val));

const chain = <A, B>(f: (a: A) => Maybe<B>, fa: Maybe<A>): Maybe<B> =>
    fa._tag === 'none' ? None() : f(fa.val);

export const Maybe = {
    Some,
    None,
    isNone,
    map,
    chain,
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...