Правильно набирая класс Box - PullRequest
0 голосов
/ 27 апреля 2018

Я следую за публикацией в блоге о функциональном программировании с использованием PureScript. Вот пример Box, который выглядит так в JavaScript:

const Box = x => ({
    map: f => Box(f(x)),
    fold: f => f(x),
    inspect: () => `Box(${x})`
});

Я хотел бы напечатать это, используя TypeScript, чтобы иметь синтаксическую проверку для кода, подобного этому:

const nextCharForNumberString = str => 
  Box(str)
  .map(s => s.trim()) 
  .map(s => new Number(s)) 
  .map(i => i + 1) 
  .map(i => String.fromCharCode(i)) 
  .fold(c => c.toLowerCase());

Я попытался напечатать поле, как это:

interface IBox<T> {
    map: <U>(T) => IBox<U>;
    fold: <U>(T) => U;
    inspect: (T) => string;
}

const Box: <T>(x: T) => IBox<T> = x => ({
    map: f => Box(f(x)),
    fold: f => f(x),
    inspect: () => `Box(${x})`
});

Это ставит меня в тупик, как правильно набирать функцию Box. В попытке упростить синтаксис я тоже попробовал это:

function Box<T>(x: T): IBox<T> {
    return {
        map: <U>(f): IBox<U> => Box(f(x)),
        fold: <U>(f): U => f(x),
        inspect: () => `Box(${x})`
    };
}

Ни одна из моих попыток не работает полностью. Я хотел бы, чтобы это было поймано во время компиляции:

const s: IBox<String> = Box(5)
    .map(x => x * x)
    .map(x => x.toString())
    .map(x => x * x)
    .fold(x => x);

Мне кажется, что это возможно с помощью TypeScript. Любое понимание будет с благодарностью!

1 Ответ

0 голосов
/ 27 апреля 2018

Конечно, я думаю, что вы довольно близки. Вот способ ввода интерфейса Box<T>:

interface Box<T> {
  map<U>(f: (t: T) => U): Box<U>;
  fold<U>(f: (t: T) => U): U;
  inspect(): string;
}

И вот способ набрать функцию Box, которая принимает аргумент типа T и выдает Box<T> (вы можете использовать как Box как имя типа, так и имя функции, так как имена и тип значения имена существуют в разных пространствах имен):

const Box = <T>(x: T): Box<T> => ({
  map: f => Box(f(x)),
  fold: f => f(x),
  inspect: () => `Box(${x})`
}); // compiles fine

Тогда вы поймаете проблему во время компиляции, как вы хотите:

const badS = Box(5)
  .map(x => x * x)
  .map(x => x.toString())
  .map(x => x * x) // error, x is a string, you cant multiply it
  .fold(x => x);

И сможете это исправить:

const goodS = Box(5)
.map(x => x * x)
.map(x => x.toString())
.fold(x => x); // goodS is type string

console.log(goodS); "25"

Надеюсь, это поможет; удачи!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...