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
    的类似实例)
  • 应该可以计算域变量集,即图像项 set和引入的变量集,给定
    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