Встраивание типов высшего порядка (монад!) в нетипизированное лямбда-исчисление

Можно кодировать различные типы в нетипизированном лямбда-исчислении с помощью функций более высокого порядка.

Examples:
zero  = λfx.      x
one   = λfx.     fx
two   = λfx.   f(fx)
three = λfx. f(f(fx))
etc

true  = λtf. t
false = λtf. f

tuple = λxyb. b x y
null  = λp. p (λxy. false)

Мне было интересно, проводились ли какие-либо исследования по внедрению других менее традиционных типов. Было бы блестяще, если бы существовала какая-нибудь теорема, утверждающая, что любой тип может быть вложен. Возможно есть ограничения, например можно вставлять только типы вида *.

Если действительно возможно представить менее традиционные типы, было бы здорово увидеть пример. Мне особенно интересно посмотреть, как выглядят члены класса монадного типа.


person TheIronKnuckle    schedule 19.01.2012    source источник


Ответы (3)


Вы путаете уровень типа с уровнем значения. В нетипизированном лямбда-исчислении нет монад. Могут быть монадические операции (уровень значения), но не монады (уровень типа). Однако сами операции могут быть одинаковыми, так что вы не потеряете никакой выразительной силы. Так что сам вопрос не имеет особого смысла.

person ertes    schedule 19.01.2012
comment
Поскольку лямбда-исчисление является полным по Тьюрингу, в нем можно закодировать любой вычислительный процесс. Я предполагаю, что вопрос именно о кодировании. Конечно, в нетипизированном исчислении нет типов, но можно закодировать некоторые объекты, которые ведут себя как типы и механизмы типизации. Точно так же, как у него нет булов и чисел, но есть соответствующие кодировки, указанные в вопросе. ответ Дэна больше соответствует этому пониманию. - person ps_ttf; 05.12.2017

Можно представить практически любой тип, который вы хотите. Но поскольку монадические операции реализуются по-разному для каждого типа, невозможно написать >>= один раз и заставить его работать для каждого экземпляра.

Однако вы можете писать универсальные функции, которые зависят от доказательства экземпляра класса типов. Рассмотрим здесь e как кортеж, где fst e содержит определение «привязки», а snd e содержит определение «возврата».

bind = λe. fst e    -- after applying evidence, bind looks like λmf. ___
return = λe. snd e  -- after applying evidence, return looks like λx. ___

fst = λt. t true
snd = λt. t false

-- join x = x >>= id
join = λex. bind e x (λz. z)

-- liftM f m1 = do { x1 <- m1; return (f x1) }
-- m1 >>= \x1 -> return (f x1)
liftM = λefm. bind e m (λx. return e (f x))

Затем вам нужно будет определить «кортеж доказательств» для каждого экземпляра Monad. Обратите внимание, что то, как мы определили bind и return: они работают так же, как и другие определенные нами "общие" методы монад: сначала им должны быть даны доказательства монадности, а затем они функционируют должным образом.

Мы можем представить Maybe как функцию, которая принимает 2 входа: первый — это функция, которую нужно выполнить, если это Just x, а второй — значение, которое нужно заменить, если оно равно Nothing.

just = λxfz. f x
nothing = λfz. z

-- bind and return for maybes
bindMaybe = λmf. m f nothing
returnMaybe = just

maybeMonadEvidence = tuple bindMaybe returnMaybe

Списки аналогичны, представляют список как его функцию складывания. Следовательно, список — это функция, которая принимает 2 входа: «против» и «пусто». Затем он выполняет foldr myCons myEmpty в списке.

nil = λcz. z
cons = λhtcz. c h (t c z)

bindList = λmf. concat (map f m)
returnList = λx. cons x nil

listMonadEvidence = tuple bindList returnList

-- concat = foldr (++) []
concat = λl. l append nil

-- append xs ys = foldr (:) ys xs
append = λxy. x cons y

-- map f = foldr ((:) . f) []
map = λfl. l (λx. cons (f x)) nil

Either также прост. Представьте любой тип как функцию, которая принимает две функции: одну для применения, если это Left, и другую для применения, если это Right.

left = λlfg. f l
right = λrfg. g r

-- Left l >>= f = Left l
-- Right r >>= f = f r
bindEither = λmf. m left f
returnEither = right

eitherMonadEvidence = tuple bindEither returnEither

Не забывайте, что функции сами (a ->) образуют монаду. И все в лямбда-исчислении является функцией... так что... не думайте об этом слишком много. ;) Вдохновлен непосредственно источником Control.Monad. Экземпляры

-- f >>= k = \ r -> k (f r) r
bindFunc = λfkr. k (f r) r
-- return = const
returnFunc = λxy. x

funcMonadEvidence = tuple bindFunc returnFunc
person Dan Burton    schedule 20.01.2012
comment
NB: это в основном то, как классы типов реализуются в GHC. Кортеж свидетельства вместо этого называется словарем класса типов (или люди, работающие на C, могут называть его виртуальной таблицей). - person Dan Burton; 02.02.2012

Ну, у нас уже есть кортежи и логические значения, поэтому мы можем представить Either и, в свою очередь, любой нерекурсивный тип суммы на основе этого:

type Either a b = (Bool, (a, b))
type Maybe a    = Either () a

И Maybe является членом класса типов Monad. Перевод в лямбда-нотацию оставляем в качестве упражнения.

person Ingo    schedule 19.01.2012