如何使用Scott编码表示嵌套类型?

时间:2015-06-04 23:04:45

标签: haskell functional-programming lambda-calculus algebraic-data-types scott-encoding

可以使用Scott编码来表示ADT,方法是通过匹配器替换产品和匹配器。例如:

data List a = Cons a (List a) | Nil

可以使用Scott Encoding编码为:

cons = (λ h t c n . c h t)
nil  = (λ c n . n)

但我无法找到如何使用SE编码嵌套类型:

data Tree a = Node (List (Tree a)) | Leaf a

怎么做?

2 个答案:

答案 0 :(得分:4)

如果Wikipedia article正确,那么

data Tree a = Node (List (Tree a)) | Leaf a

有Scott编码

node = λ a . λ node leaf . node a
leaf = λ a . λ node leaf . leaf a

看起来Scott编码对(嵌套)类型无动于衷。它所关心的只是向构造函数提供正确数量的参数。

答案 1 :(得分:3)

Scott编码基本上通过其case表达式的类型表示T。所以对于列表,我们将定义一个case表达式,如下所示:

listCase :: List a -> r -> (a -> List a -> r) -> r
listCase []     n c = n
listCase (x:xs) n c = c x xs

这给了我们类似的类比:

case xs of { [] -> n ; (x:xs) -> c }
=
listCase xs n (\x xs -> c)

这给出了一个类型

newtype List a = List { listCase :: r -> (a -> List a -> r) -> r }

构造函数只是选择适当分支的值:

nil :: List a
nil = List $ \n c -> n

cons :: a -> List a -> List a
cons x xs = List $ \n c -> c x xs

我们可以向后工作,从枯燥的案例表达式到案例函数,再到树的类型:

case t of { Leaf x -> l ; Node xs -> n }

应该大致像

treeCase t (\x -> l) (\xs -> n)

所以我们得到

treeCase :: Tree a -> (a -> r) -> (List (Tree a) -> r) -> r
treeCase (Leaf x)  l n = l x
treeCase (Node xs) l n = n xs

newtype Tree a = Tree { treeCase :: (a -> r) -> (List (Tree a) -> r) -> r }

leaf :: a -> Tree a
leaf x = Tree $ \l n -> l x

node :: List (Tree a) -> Tree a
node xs = Tree $ \l n -> n xs
斯科特编码非常容易,因为他们只是案件。教会编码是折叠,对于嵌套类型而言是众所周知的。