考虑到通用多态性的功能,我试图理解递归代数数据类型的定义、去和编码。例如,我尝试通过实现递归类型的二叉树
data BTAlg x = Empty | Leaf x x
type BT = forall z. ((BTAlg z) -> z) -> z
直觉是二叉树的类型应该在所有T
配备常量e: T
和二元运算的类型中是初始的m: T -> T -> T
,即函子上的“初始模块” BTAlg
。换句话说,元素 ofBT
是为任何此类模块分配 的元素的一种T
方式T
。
自身的模块结构BT
可以通过
initial_module :: (BTAlg BT) -> BT
initial_module = \s -> case s of
Empty -> (\f -> (f Empty))
Leaf x y -> (\f -> (f (Leaf (x f) (y f))))
作为BT
对. x:BT
_ BT
_x
decode_encode :: BT -> BT
decode_encode x = x initial_module
但是,此代码导致我无法处理的类型错误:
Couldn't match expected type `(BTAlg z -> z) -> z'
with actual type `BT'
Expected type: BTAlg ((BTAlg z -> z) -> z) -> (BTAlg z -> z) -> z
Actual type: BTAlg BT -> (BTAlg z0 -> z0) -> z0
In the first argument of `x', namely `initial_module'
In the expression: x initial_module
这里有什么问题?我不知道为什么类型检查器不承认通用类型参数z
必须专门化才能适用BT
于;写作也无济于事。x
x
initial_module
(x :: ((BTAlg BT) -> BT) -> BT) initial_module
关于定义动机的附录decode_encode
:我想说服自己BT
实际上与标准实现“同构”
data BTStd = StdEmpty | StdLeaf BTStd BTStd
二叉树;虽然我不知道如何在 Haskell 中做到这一点,但首先要构建映射BT -> BTStd
并BTStd -> BT
在两种实现之间来回切换。
的定义是对规范模块结构toStandard: BT -> BTStd
的通用属性的应用:BT
BTAlg
BTStd
std_module :: (BTAlg BTStd) -> BTStd
std_module s = case s of
Empty -> StdEmpty
Leaf x y -> StdLeaf x y
toStandard: BT -> BTStd
toStandard x = x std_module
对于解码功能fromStandard: BTStd -> BT
,我想做以下事情:
fromStandard :: BTStd -> BT
fromStandard s = case s of
StdEmpty -> initial_module Empty
StdLeaf x y -> initial_module (Leaf (fromStandard x) (fromStandard y))
但是,这会产生与上述直接定义相同的打字问题decode_encode
:
Couldn't match expected type `BT'
with actual type `(BTAlg z0 -> z0) -> z0'
In the return type of a call of `fromStandard'
Probable cause: `fromStandard' is applied to too few arguments
In the first argument of `Leaf', namely `(fromStandard x)'
In the first argument of `initial_module', namely
`(Leaf (fromStandard x) (fromStandard y))'
谢谢!