一般问题
我有一对数据类型,它们是表示同一事物的两种不同方式,一种在 String 中记录变量名,而另一种在 Int 中记录变量名。目前,它们都已定义。但是,我只想描述第一种表示,而第二种表示将由某种关系生成。
具体例子
具体来说,第一个是 STLC 术语全域的用户定义版本,而第二个是同一事物的 de Bruijn 索引版本:
{-# LANGUAGE RankNTypes, GADTs, DataKinds, TypeOperators, KindSignatures, PolyKinds, TypeFamilies, UndecidableInstances, FunctionalDependencies, FlexibleInstances #-}
-- * Universe of Terms * --
data Term :: Type -> * where
Var :: Id -> Term a
Lam :: Id -> Type -> Term b -> Term (a :-> b)
App :: Term (a :-> b) -> Term a -> Term b
Let :: Id -> Term a -> Term b -> Term b
Tup :: Term a -> Term b -> Term (a :*: b)
Lft :: Term a -> Term (a :+: b)
Rgt :: Term b -> Term (a :+: b)
Tru :: Term Boolean
Fls :: Term Boolean
Uni :: Term Unit
data TermIn :: Type -> * where
VarI :: Idx -> Info -> TermIn a
LamI :: Type -> TermIn b -> Info -> TermIn (a :-> b)
AppI :: TermIn (a :-> b) -> TermIn a -> TermIn b
LetI :: TermIn a -> TermIn b -> Info -> TermIn b
TupI :: TermIn a -> TermIn b -> TermIn (a :*: b)
TruI :: TermIn Boolean
FlsI :: TermIn Boolean
UniI :: TermIn Unit
-- * Universe of Types * --
data Type
= Type :-> Type
| Type :*: Type
| Type :+: Type
| Boolean
| Unit
| Void
-- * Synonyms * --
type Id = String -- * variable name
type Idx = Int -- * de-brujin's index
data Info = Rec Id String -- * store original name and extra info
已经在Term
and上定义了一个关系TermIn
:
class DeBruijnPair a b | a -> b, b -> a where
decode :: b -> a
encode :: a -> b
instance DeBruijnPair (Term a) (TermIn a) where
decode = undefined
encode = undefined
请注意,由于原始名称Term
存储在 中,因此到和返回TermIn
之间存在一对一的映射。Term
TermIn
重述问题
现在您可以看到涉及多少样板,我想使用我定义的一些优雅的抽象Term
和类型输出的一些函数来摆脱它TermIn
。只是为了提供更多上下文,我正在为不同的 lambda 演算公式创建许多这样的外部和 de Bruijn 表示对,并且一对一的关系适用于所有这些。