Логическая логика - PullRequest
       79

Логическая логика

1 голос
/ 31 марта 2020

Я пытаюсь грок комбинаторов, поэтому я написал основные c единицы: K и S в Typescript:

const K: Kestrel = a => b => a;
const S: Starling = a => b => c => a(c)(b(c));

Затем я следовал статье в Википедии о логических логиках SKI c:

TRUE = K
FALSE = SK

поэтому:

const TRUE: True = K;
const FALSE = S(K);

И это проходит базовые c тесты:

const t = () => true;
const f = () => false;

test('Ktf = (TRUE)tf = t', () => {
  const actual = TRUE(t)(f)();
  expect(actual).toBe(K(t)(f)());
  expect(actual).toBe(true);
});

test('SKxy = y', () => {
  expect(S(K)(t)(f)()).toBe(false);
  expect(FALSE(t)(f)()).toBe(false);
});

Пока все хорошо, но когда дело доходит до NOT Википедия говорит:

NOT = (FALSE)(TRUE) = (SK)(K)
(TRUE)NOT = TRUE(FALSE)(TRUE) = FALSE
(FALSE)NOT = FALSE(FALSE)(TRUE) = TRUE

Я написал код и тесты и получил:

const NOT = S(K)(K);

test('(TRUE)NOT = FALSE', () => {
  expect(TRUE(NOT)(t)(f)()).toBe(false); // <- see these () after (t)(f)?
  expect(TRUE(NOT)(f)(t)()).toBe(true);
});

test('(FALSE)NOT = TRUE', () => {
  expect(FALSE(NOT)(t)(f)).toBe(true); // <- here we don't have these ()
  expect(FALSE(NOT)(f)(t)).toBe(false);
});

Мой вопрос касается двух строк, которые я выделил комментариями: зачем проходить тесты, мне нужна эта асимметрия между TRUE и FALSE? Похоже, я следовал всем деталям в реализации K и S, но в случае TRUE(NOT)(t)(f) я получаю функцию () => false, а в случае FALSE(NOT)(t)(f) я получаю false.

Есть ли какие-то детали, которые я пропустил, или Википедия недостаточно точна в определениях?

PS: Вот код: https://repl.it/repls/FuchsiaFuchsiaTruetype

1 Ответ

2 голосов
/ 31 марта 2020

Две вещи: 1. Ваша реализация NOT неверна, и 2. Асимметрия - это просто совпадение.

1. совпадение:

Обратите внимание, что и TRUE, и FALSE являются функциями карри, которые ожидают еще двух аргументов для оценки.

Теперь проверьте этот факт:

FALSE(NOT)(t) === t

FALSE фактически не заботится о 1-м аргументе, и все, что он делает, это просто возвращает 2-й аргумент. Таким образом, вы получаете t в качестве возвращаемого значения, а когда вы делаете FALSE(NOT)(t)(f), вы фактически вызываете t(f), где f - бесполезный аргумент, и это дает true. Таким образом, совпадение.

2. реализация NOT

страница Википедии записывает NOT как постфиксный оператор, но это просто буквальное выражение, которое они используют для записи идеи. В JS коде вы не можете написать то же самое.

(T) NOT = T (F) (T) = F

Обратите внимание, что NOT расширяется как два аргумента для передачи функция до этого. Чтобы реализовать эту идею в JS, вам нужно написать:

const NOT = b => b(S(K))(K);

и вернуть вызывающую подпись обратно в нормальную форму: NOT(TRUE).

Я изменил ваш оригинальный код здесь: https://repl.it/@hackape / KnowledgeableWealthyDowngrade

...