Преобразование из церковного кодирования в цифры - PullRequest
2 голосов
/ 04 ноября 2019

Я пытаюсь преобразовать кодировку церкви в цифры. Я определил свое собственное лямбда-определение следующим образом:

type Variable = String

data Lambda = Lam Variable Lambda
            | App Lambda Lambda
            | Var Variable
            deriving (Eq, Show)

Я уже написал преобразование чисел в церковное кодирование, и оно работает так, как я ожидаю, вот как я его определил:

toNumeral :: Integer -> Lambda
toNumeral n = Lam "s" (Lam "z" (wrapWithAppS n (Var "z")))
  where
    wrapWithAppS :: Integer -> Lambda -> Lambda
    wrapWithAppS i e
        | i == 0 = e
        | otherwise = wrapWithAppS (i-1) (App (Var "s") e)

Я запустил свои собственные тесты и вот выходные данные терминала при тестировании на 0, 1 и 2:

*Church> toNumeral 0
Lam "s" (Lam "z" (Var "z"))
*Church> toNumeral 1
Lam "s" (Lam "z" (App (Var "s") (Var "z")))
*Church> toNumeral 2
Lam "s" (Lam "z" (App (Var "s") (App (Var "s") (Var "z"))))

Теперь я пытаюсь сделать наоборот, и я просто не могу обернуть головувокруг аргументов, которые должны быть переданы. Вот что у меня есть:

fromNumeral :: Lambda -> Maybe Integer
fromNumeral  (Lam s (Lam z (App e (Var x))))
    | 0 == x = Just 0
    | ...

Я пытался заменить (App e (Var x)) на (Var x), но я получаю эту ошибку для обоих случаев, когда пытаюсь проверить свой базовый случай преобразования церковной кодировки от 0 до Just 0:

*** Exception: Church.hs:(166,1)-(167,23): Non-exhaustive patterns in function fromNumeral

То, как я понимаю лямбда-кодировку для 3 чисел, таково:

0: \ s. \ Г. z

1: \ s. \ Г. sz

2: \ s. \ Г. s (sz)

Итак, я предполагаю, что моя логика верна, но мне трудно понять, как будет происходить обратное преобразование. Я довольно новичок в Haskell, поэтому любая помощь в объяснении того, что я могу делать неправильно, очень ценится.

1 Ответ

3 голосов
/ 04 ноября 2019

Вы должны соответствовать внешнему (Lam "s" (Lam "z" )), но внутренняя цепочка App s должна быть рекурсивно проанализирована, отражая способ ее построения:

fromNumeral (Lam s (Lam z apps)) = go apps
    where
        go (Var x) | x == z = Just 0
        go (App (Var f) e) | f == s = (+ 1) <$> go e
        go _ = Nothing

fromNumeral _ = Nothing
...