我正在尝试在 Haskell 中实现 System-F 风格的数据结构。
我将使用A <B>
to 表示将术语A
应用于类型B
只是为了使其明确(也使用大写字母表示类型)。
假设Tree <T>
是具有 type 值的二叉树的类型T
。我们想找到一种可以充当Tree <T>
. 构造函数有以下三种:
EmptyTree <T> : (Tree <T>)
Leaf <T> : T → (Tree <T>)
Branch <T> : (Tree <T>) → (Tree <T>) → (Tree <T>)
因此,我认为,由于 Girard 的一些聪明才智,我们可以使用以下
Tree T = ∀ A. A → (T → A) → (A → A → A) → A
从中
Empty <T>
= ΛA.λa:A.λf:(T → A).λg:(A → A → A).
a
Leaf <T> (x:T)
= ΛA.λa:A.λf:(T → A).λg:(A → A → A).
f x
Branch <T> (t1:Tree <T>) (t2:Tree <T>)
= ΛA.λa:A.λf:(T → A).λg:(A → A → A).
g (t1 <A> a f g) (t2 <A> a f g)
我在 Haskell 中发现了这些东西所需的指令,我认为我没有遗漏任何指令。所以在 Haskell 中:
{-# LANGUAGE RankNTypes #-}
type T t = forall a.a -> (t -> a) -> (a -> a -> a) -> a
empty :: T t
empty = \a _ _ -> a
leaf :: t -> T t
leaf x = \_ f _ -> f x
fork :: T t -> T t -> T t
fork t1 t2 = \a f g -> g (t1 a f g) (t2 a f g)
到目前为止,所有这些都可以编译并且似乎可以工作。当我尝试Show
为我的T t
类型创建一个实例时,问题就出现了。我添加了更多指令:
{-# LANGUAGE RankNTypes, TypeSynonymInstances, FlexibleInstances #-}
和打印树的功能
displayTree :: Show t => T t -> String
displayTree t = t displayEmpty show displayFork
有适当的助手displayEmpty :: String
和displayFork :: String -> String -> String
. 这也可以编译和工作(直到漂亮)。现在,如果我尝试实例T t
化为Show
instance Show t => Show (T t) where
show = displayTree
尝试编译时出现以下错误:
Illegal polymorphic or qualified type: T t
In the instance declaration for 'Show (T t)'
我(想我)理解它们存在的必要性TypeSynonymInstances
和FlexibleInstances
实用性原因,但我不明白为什么我的类型T t
仍然不能被声明为Show
. 有没有办法做到这一点,什么属性T t
意味着这在我的代码中目前存在问题?