Может быть, тип в машинописи - PullRequest
0 голосов
/ 29 мая 2018

Я хотел бы создать тип Maybe a в машинописи а-ля Хаскелл:

data Maybe a = Just a | Nothing

Кажется, что способ сделать это в typescript - это:

interface Nothing { tag "Nothing }
type Maybe<T> = T | Nothing

Я хотел бы сделать функцию:

function foo(x : string) : Maybe<T> {
    return Nothing
}

сродни:

foo : String -> Maybe a
foo _ = Nothing

Однако это не работает в typescript.Как правильно вернуть значение Nothing в машинописи?Я хотел бы избежать использования null, если это возможно.

___________________________________________________-

Редактировать: Было бы действительно приятно , если бы функция foo вернула бы значение Nothing, потому что я хотел быпозже сопоставить шаблон с конструктором значений, то есть:

case blah blah of 
    | Just x -> x + x
    | Nothing -> "no words"

Ответы [ 2 ]

0 голосов
/ 17 июля 2019
enum Nothing {
  Nothing = 'Nothing'
}

type Maybe<A> = A | Nothing
type MaybeNumber = Maybe<number>

const isNothing = (m: MaybeNumber): m is Nothing => m === Nothing.Nothing 

const foo = (m: MaybeNumber) => {
  if (isNothing(m)) {
    return Nothing.Nothing
  } else {
    return m + 1
  }
}

foo(1) // ✔️
foo('Nothing') // ❌
foo(Nothing.Nothing) // ✔️

или без использования enum с использованием string literal type

const Nothing = '__nothing__'

type Maybe<A> = A | Nothing
type MaybeNumber = Maybe<number>

const isNothing = (m: MaybeNumber): m is Nothing => m === Nothing 

const foo = (m: MaybeNumber) => {
  if (isNothing(m)) {
    return Nothing
  } else {
    return m + 1
  }
}

foo(1) // ✔️
foo(Nothing) // ✔️
foo('__nothing__') // ✔️

или с символами

const nothing = Symbol('Nothing')
type Nothing = typeof nothing

type Maybe<A> = A | Nothing
type MaybeNumber = Maybe<number>

const isNothing = (m: MaybeNumber): m is Nothing => m.toString() === 'Symbol(Nothing)' 

const foo = (m: MaybeNumber) => {
  if (isNothing(m)) {
    return nothing
  } else {
    return m + 1
  }
}

foo(1) // ✔️
foo(nothing) // ✔️

в прямом эфире stackblitz

0 голосов
/ 29 мая 2018

В зависимости от случая это может быть void, undefined или ? необязательный модификатор для свойств и параметров.

Это:

function foo(x : string) : number | void {
    // returns nothing
}

voidи undefined типы совместимы, но между ними есть некоторая разница.Первый предпочтителен для типов возвращаемых функций, поскольку последний требует, чтобы функция имела оператор return:

function foo(x : string) : number | undefined {
    return;
}

Maybe можно реализовать с универсальным типом.Явный тип Nothing может быть реализован с уникальным символом:

const Nothing = Symbol('nothing');
type Nothing = typeof Nothing;
type Maybe<T> = T | Nothing;

function foo(x : string) : Maybe<number> {
    return Nothing;
}

или классом (частные поля могут использоваться для предотвращения приёма):

abstract class Nothing {
    private tag = 'nothing'
}
type Maybe<T> = T | typeof Nothing;

function foo(x : string) : Maybe<number> {
    return Nothing;
}

Обратите внимание, что типы классов обозначают класстип экземпляра и требуется использовать typeof при обращении к классу.

Или объект (если желательна утка):

const Nothing: { tag: 'Nothing' } = { tag: 'Nothing' };
type Nothing = typeof Nothing;
type Maybe<T> = T | Nothing;

function foo(x : string) : Maybe<number> {
    return Nothing;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...