Haskell 了解匹配在用户定义类型上建立索引的数据类型的模式所涉及的强制转换

Haskell 了解匹配在用户定义类型上建立索引的数据类型的模式所涉及的强制转换,haskell,casting,ghc,type-families,data-kinds,Haskell,Casting,Ghc,Type Families,Data Kinds,因此,我在Haskell中使用了数据种类和类型族,并开始研究生成的核心GHC 下面是一个小测试用例来激发我的问题: {-# LANGUAGE GADTs #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} module TestCase where data Ty = TyBool | TyInt type family InterpTy (t :: Ty)

因此,我在Haskell中使用了
数据种类
类型族
,并开始研究生成的核心GHC

下面是一个小测试用例来激发我的问题:

{-# LANGUAGE GADTs #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}

module TestCase where

data Ty = TyBool | TyInt

type family InterpTy (t :: Ty) :: *
type instance InterpTy TyBool = Bool
type instance InterpTy TyInt  = Int

data Expr (a :: Ty) where
  I :: Int  -> Expr TyInt
  B :: Bool -> Expr TyBool

eval :: Expr a -> InterpTy a
eval (I i) = i
eval (B b) = b
让我们看一下为
eval
函数生成的核心

TestCase.eval =
  \ (@ (a_aKM :: TestCase.Ty)) (ds_dL3 :: TestCase.Expr a_aKM) ->
    case ds_dL3 of _ [Occ=Dead] {
      TestCase.I dt_dLh i_as6 ->
        i_as6
        `cast` (Sub (Sym TestCase.TFCo:R:InterpTyTyInt[0])
                ; (TestCase.InterpTy (Sym dt_dLh))_R
                :: GHC.Types.Int ~# TestCase.InterpTy a_aKM);
      TestCase.B dt_dLc b_as7 ->
        b_as7
        `cast` (Sub (Sym TestCase.TFCo:R:InterpTyTyBool[0])
                ; (TestCase.InterpTy (Sym dt_dLc))_R
                :: GHC.Types.Bool ~# TestCase.InterpTy a_aKM)
    }
显然,我们需要携带有关特定分支中
a
可能是什么的信息。如果我不在Datakind上建立索引,也不使用TypeFamilies,那么转换就更容易理解了

应该是这样的:

Main.eval =
  \ (@ a_a1hg) (ds_d1sQ :: Main.Simpl a_a1hg) ->
    case ds_d1sQ of _ [Occ=Dead] {
      Main.I' dt_d1to i_aFa ->
        i_aFa
        `cast` (Sub (Sym dt_d1to) :: GHC.Integer.Type.Integer ~# a_a1hg);
      Main.B' dt_d1tk b_aFb ->
        b_aFb `cast` (Sub (Sym dt_d1tk) :: GHC.Types.Bool ~# a_a1hg)
    }
这一点我可以完全理解,在
TypeFamilies
示例中困扰我的是这一部分:

(Sub (Sym TestCase.TFCo:R:InterpTyTyInt[0])
      ; (TestCase.InterpTy (Sym dt_dLh))_R
      :: GHC.Types.Int ~# TestCase.InterpTy a_aKM);
第二句话让我很困惑。分号在那里做什么?这似乎有点不合适,还是我遗漏了什么?有没有一个地方可以让我读到这篇文章(如果你能推荐的话,我很乐意接受)

亲切问候,


raichoo

分号是强制传递的语法

关于系统FC的最新论文(截至2014年9月)来自ICFP 2014

特别是,在那篇文章的图3中,我们看到了强制的语法。"γ₁;γ₂" 是强制传递性。如果γ₁ 是见证“τ”的胁迫₁ ~ τ₂“和γ₂ 是见证τ的胁迫₂ ~ τ₃ 然后是“γ”₁;γ₂“是见证τ的胁迫₁ ~ τ₃.

在本例中,当您编写
eval(I)=I
时,编译器在右侧看到的是
Int
类型的值,它需要的(来自函数的返回类型)是
InterpTy a
。因此现在需要构造一个证明
Int~InterpTy a

非正式地,(从右到左阅读,忽略角色-有关详细信息,请参阅链接文章):

  • 通过进行GADT模式匹配,我们了解到“
    a~Int
    ”(即
    dt\u dLh
  • 所以我们对它应用
    Sym
    ,得到“
    Int~a
  • 然后应用
    InterpTy
    族获得“
    InterpTy Int~InterpTy a
    ”(这是/congrence/的一个实例)
  • 然后我们用“
    Sym interptyint
    ”(这是公理的翻转版本,说明“
    interptyint~Int
    ”)来传递它,以获得我们所追求的强制:“
    Int~InterpTy a

  • 该死的,我读了那篇文章,但不知怎的我忘了:D谢谢^^