Haskell 一类类型变换替换 设置
考虑在一类函数符号上参数化的一类术语Haskell 一类类型变换替换 设置,haskell,programming-languages,agda,type-theory,Haskell,Programming Languages,Agda,Type Theory,考虑在一类函数符号上参数化的一类术语节点 和一类变量var: 数据项节点变量 =瓦特姆!变量 |有趣的词!节点!(向量(术语节点变量)) 推导(Eq、Ord、Show) 实例函子(术语节点),其中 fmap f(VarTerm var)=VarTerm(f var) fmap f(FunTerm n cs)=FunTerm n(Vector.map(fmap f)cs) 实例Monad(术语节点),其中 纯=变项 join(VarTerm)=术语 join(FunTerm n cs)=FunTe
节点
和一类变量var
:
数据项节点变量
=瓦特姆!变量
|有趣的词!节点!(向量(术语节点变量))
推导(Eq、Ord、Show)
实例函子(术语节点),其中
fmap f(VarTerm var)=VarTerm(f var)
fmap f(FunTerm n cs)=FunTerm n(Vector.map(fmap f)cs)
实例Monad(术语节点),其中
纯=变项
join(VarTerm)=术语
join(FunTerm n cs)=FunTerm n(Vector.map join cs)
这是一种有用的类型,因为我们使用术语节点Var
对开放术语进行编码,
带有术语节点Void
的封闭术语,以及带有术语节点()
的上下文
我们的目标是在术语
s上定义一种最合适的替换类型
可能的方式。这是第一次尝试:
newtype替换(节点∷ 类型(var)∷ (类型)
=替换{fromSubstitution∷ 映射变量(术语节点变量)}
推导(Eq、Ord、Show)
现在,让我们定义一些与替换相关的辅助值:
subst∷ 替换节点变量→ 术语节点变量→ 术语节点变量
subst s(VarTerm var)=fromMaybe(MkVarTerm var)
(Map.lookup变量(froms))
subst s(FunTerm n ts)=FunTerm n(Vector.map(subst s)ts)
身份∷ 替换节点变量
identity=Substitution Map.empty
--法律:
--
-- 1. 统一性:
-- ∀ s∷ 代换→ s≡ (s)∘ (身份)≡ (身份∘ (s)
-- 2. 结合性:
-- ∀ a、 b,c∷ 代换→ ((a)∘ (b)∘ (c)≡ (一)∘ (b)∘ c) )
-- 3. 幺半群作用:
-- ∀ x、 y∷ 代换→ subst(y)∘ 十)≡ (第y部分第x部分)
(∘) ∷ (Ord var)
⇒ 替换节点变量
→ 替换节点变量
→ 替换节点变量
s1∘ s2=替换
(地图1)
(λ _ _ → 错误“这永远不会发生”)
(Map.Map(subst s1)(来自替换s2))
((从替换s1)`Map.difference`(从替换s2)))
显然,(替换n v,∘, 标识)
是幺半群(忽略Ord
对∘
)和(名词v,subst)
是
替换n v
现在假设我们想让这个方案编码替换
这将更改变量类型。这看起来像某种类型的subscat
满足以下模块签名的:
数据子目录(节点∷ 类型)(域变量∷ 类型(Codoma因瓦)∷ (类型)
= … ∷ 类型
替补∷ 子节点domcod→ 术语节点dom→ 术语节点cod
身份∷ 子节点变量
(∘) ∷ (作战需求文件1、作战需求文件2、作战需求文件3)
→ 子节点v2 v3
→ 子节点v1 v2
→ 子节点v1 v3
这几乎是一个Haskell类别
,但是对于Ord
的约束∘代码>。
你可能会认为如果,∘, identity)以前是一个幺半群,
而subst
以前是一个幺半群动作,那么subst
现在应该是一个类别
动作,但实际上类别动作只是函子(在本例中,
从Hask的一个子类别到Hask的另一个子类别的函子)
现在,关于subscat
,我们希望有一些属性是正确的:
substicatnode var Void
应为接地替换类型substitute-cat-Void-var
应为平面替换类型实例(Eq节点、Eq dom、Eq cod)⇒ Eq(子节点dom cod)
应存在(以及Ord
和Show
的类似实例)subscat节点domcod
替代
实现中的等价物subscat
最简单的方法是
概括替换:
newtype subscat(节点∷ 类型(dom)∷ 类型(cod)∷ (类型)
=subscat{fromsubscat∷ 映射dom(术语节点cod)}
推导(Eq、Ord、Show)
不幸的是,这不起作用,因为当我们运行subst
时,它可能是
我们正在运行替换的术语包含
不在地图的领域
。我们可以在替换
由于dom~cod
,但在subscat
中,我们无法处理这些问题
变量
我的下一个尝试是通过包含函数
类型dom→ cod
:
数据子目录(节点∷ 类型(dom)∷ 类型(cod)∷ (类型)
=子类
!(映射dom(术语节点cod))
!(多姆→ (化学需氧量)
但是,这会导致一些问题。首先,由于subscat
现在包含
函数,它不能再具有Eq
、Ord
或Show
实例。我们不能
只需忽略dom→ 比较是否相等时的cod
字段,因为
替换的语义根据其值而变化
不再出现subscat节点var Void
表示接地类型的情况
替换;事实上,substicatnode var Void
是无人居住的
埃尔迪·格格在Facebook上建议我使用以下定义:
newtype subscat(节点∷ 类型(dom)∷ 类型(cod)∷ (类型)
=子类(dom)→ 术语节点(cod)
这当然是一个迷人的前景。这有一个明显的分类
类型:由Term节点上的Monad
实例给出的Kleisli类别
不确定这是否与通常的替代概念相符
type Subst node i j = Map i (Term node j)
subst :: Ord i => Subst node i j -> Term node i -> Maybe (Term node j)
subst sub (VarTerm x) = Map.lookup x sub
subst sub (FunTerm f ts) = FunTerm f <$> traverse (subst sub) ts
data Nat = Z | S Nat deriving (Eq, Show)
-- {-# language TypeInType, GADTs, TypeFamilies, ScopedTypeVariables,
-- FlexibleInstances, MultiParamTypeClasses, RankNTypes,
-- TypeApplications, StandaloneDeriving #-}
data Fin n where
FZ :: Fin (S n)
FS :: Fin n -> Fin (S n)
deriving instance Eq (Fin n)
deriving instance Ord (Fin n)
deriving instance Show (Fin n)
data Term node (n :: Nat) where
VarTerm :: !(Fin n) -> Term node n
FunTerm :: !node -> !(Vector (Term node n)) -> Term node n
deriving instance Eq node => Eq (Term node n)
deriving instance Ord node => Ord (Term node n)
deriving instance Show node => Show (Term node n)
data Vec a n where
Nil :: Vec a Z
(:>) :: a -> Vec a n -> Vec a (S n)
infixr 5 :>
deriving instance Eq a => Eq (Vec a n)
deriving instance Ord a => Ord (Vec a n)
deriving instance Show a => Show (Vec a n)
type Subst node i j = Vec (Term node j) i
subst :: Subst node i j -> Term node i -> Term node j
subst (t :> _ ) (VarTerm FZ) = t
subst (_ :> ts) (VarTerm (FS x)) = subst ts (VarTerm x)
subst sub (FunTerm f ts) = FunTerm f (Vector.map (subst sub) ts)
comp :: Subst node i j -> Subst node j k -> Subst node i k
comp Nil sub2 = Nil
comp (t :> ts) sub2 = subst sub2 t :> comp ts sub2
class Tabulate n where
tabulate :: (Fin n -> Term node m) -> Subst node n m
instance Tabulate Z where
tabulate f = Nil
instance Tabulate n => Tabulate (S n) where
tabulate f = f FZ :> tabulate (f . FS)
idSubst :: Tabulate n => Subst node n n
idSubst = tabulate VarTerm
{-# LANGUAGE TypeFamilies, TypeOperators #-}
import Data.MemoTrie
import Control.Category.Constrained
newtype SubstCat node dom cod = SubstCat (dom :->: Term node cod)
instance Category (SubstCat node) where
type Object (SubstCat node) a = HasTrie a
id = SubstCat (trie VarTerm)
SubstCat f . SubstCat g = SubstCat $ fmap (untrie f =<<) g