可以使用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
怎么做?
答案 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
斯科特编码非常容易,因为他们只是案件。教会编码是折叠,对于嵌套类型而言是众所周知的。