簡體   English   中英

GHC如何處理核心中的類型類和實例?

[英]How does GHC handle typeclass and instance in core?

我將以下Haskell代碼編譯為核心:

class FunClass a where
  functionInClass :: a -> ()

data MyData = MyData
data YourData = YourData

instance FunClass MyData where
  functionInClass a = ()
instance FunClass YourData where
  functionInClass a = ()

valueA :: ()
valueA = functionInClass MyData

valueB :: ()
valueB = functionInClass YourData

並獲得以下核心綁定(我刪除了一些不相關的樣板):

 $cfunctionInClass :: MyData -> ()
 [LclId]
 $cfunctionInClass = \ _ [Occ=Dead] -> break<3>() ()

 $fFunClassMyData [InlPrag=INLINE (sat-args=0)] :: FunClass MyData
 $fFunClassMyData
   = $cfunctionInClass
     `cast` (Sym (N:FunClass[0] <MyData>_N)
             :: Coercible (MyData -> ()) (FunClass MyData))

 $cfunctionInClass :: YourData -> ()
 [LclId]
 $cfunctionInClass = \ _ [Occ=Dead] -> break<2>() ()

 $fFunClassYourData [InlPrag=INLINE (sat-args=0)] :: FunClass YourData
 $fFunClassYourData
   = $cfunctionInClass
     `cast` (Sym (N:FunClass[0] <YourData>_N)
             :: Coercible (YourData -> ()) (FunClass YourData))

 valueA :: ()
 [LclIdX]
 valueA
   = break<1>() functionInClass @ MyData $fFunClassMyData MyData

 valueB :: ()
 [LclIdX]
 valueB
   = break<0>()
     functionInClass @ YourData $fFunClassYourData YourData

我的問題是:

  1. 為什么兩個cfunctionInClass共享相同的名稱? 我們如何區分它們?

  2. cast到底能做什么?

  3. mg_binds ModGuts之外是否有任何與mg_binds ModGuts / instance相關的mg_binds ModGuts

不知道(i)確切的GHC版本,(ii)使用的確切ghc命令行,以及(iii)編譯文件的全部內容,很難復制您要查詢的核心輸出,但是這里有一些答案:

1)生成內核時,您可能提供了-dsuppress-uniques標志,使用了其他暗示它的標志,或者使用了默認版本的GHC的較早版本。 此標志使GHC從核心輸出中消除用於創建唯一名稱的少量隨機后綴。 如果刪除標志或添加顯式的-dno-suppress-uniques ,則應該看到唯一的名稱,例如$cfunctionInClass_r1cH$cfunctionInClass_r1dh

2)Core是一種類型化的語言,並且(廣泛地)使用函數cast轉換來更改表達式的類型。 請注意,它不會更改表達式本身的內部表示形式,因此只能用於在內存中具有相同內部表示形式的類型之間進行切換。

您會在各處看到使用newtypes代碼的newtypes 例如代碼:

newtype MyInt = MyInt Int
inc (MyInt n) = MyInt (n + 1)

創建(未優化的)核心:

inc1 :: MyInt -> Int
inc1
  = \ (ds :: MyInt) ->
      + @ Int $fNumInt (ds `cast` (N:MyInt[0] :: MyInt ~R# Int)) (I# 1#)
inc :: MyInt -> MyInt
inc
  = inc1
    `cast` (<MyInt>_R ->_R Sym (N:MyInt[0])
            :: (MyInt -> Int) ~R# (MyInt -> MyInt))

有幾個演員。

的方式cast作品中,左手側`cast`操作者是一個正常的核心術語(例如,可變或其他表達式)表示其類型被改變的值; 右側是稱為“強制”的東西,它是編譯器構造的一種證據,用於證明兩種類型在表示上是等效的(即,具有相同的內存中表示,因此可以安全地強制)。 例如,在上面的新類型示例中,第一次強制轉換的強制是:

N:MyInt[0] :: MyInt ~R# Int

是強制值N:MyInt[0]其類型是MyIntInt的表示相等性( MyInt ~R# )。 (從技術上講, N:MyInt[0]是強制類型,類型是給定的表示相等性,但是這種區別並不重要。)如果您熟悉Curry-Howard同構,則可以將值視為證明的證明。它們的類型,這是GHC膽量深處的一個例子—值/類型N:MyInt[0]證明了它的類型/種類,即新類型及其內容的表示性相等,從而使演員可以地點。

在您的示例中,強制轉換:

$fFunClassMyData [InlPrag=INLINE (sat-args=0)] :: FunClass MyData
$fFunClassMyData
  = $cfunctionInClass
    `cast` (Sym (N:FunClass[0] <MyData>_N)
            :: Coercible (MyData -> ()) (FunClass MyData))

這是一種復雜的說法,即GHC表示類型類的實例字典,該實例類僅具有一個函數,與表示包含該類型的函數的新類型的方式幾乎相同,與表示函數值本身的方式相同。 因此,函數值$cfunctionInClass可以直接轉換為字典值。

但是,如果您向類型類添加了另一個函數:

class FunClass a where
  functionInClass :: a -> ()
  anotherFunction :: a

這些強制轉換將從字典的定義中消失,它們看起來更像您期望的那樣:

$fFunClassMyData
$fFunClassMyData = C:FunClass $cfunctionInClass $canotherFunction

重要的是要注意, cast在最終代碼中不做任何事情。 一旦核心轉換為無類型STG並最終CMM和裝配, cast調用優化掉了,因為它們不影響價值,他們只修改編譯時間類型,以滿足核心typechecker。 因此,除非您正在調試GHC,否則您可能根本不在乎強制轉換,因此應考慮不操作。 您可以使用-dsuppress-coercions (由-dsuppress-all-dsuppress-coercions一些細節:

$fFunClassYourData = $cfunctionInClass1 `cast` <Co:3>

並假裝x `cast` <Co:xxx>完全等同於x 在你上面的例子中,字典只為類型類的單一實例功能,所以這是真的一樣達到強制轉換的類型為:

$fFunClassMyData = $cFunctionInClass

3)當然。 附加類和實例信息被存儲在mg_tcsmg_insts領域ModGuts分別。 大致來說, mg_binds包含代碼生成所需的信息,而mg_tcsmg_insts包含生成接口文件所需的信息。

對GHC編譯器代碼的有用參考

ghc/compiler/coreSyn/PprCore.hs漂亮打印核心模塊。 如果您想知道核心產品的來源,那就是它。 (例如, ppr_expr add_par (Cast expr co) = ...是負責漂亮地打印`cast`運算符的代碼。

ghc/compiler/coreSyn/CoreSyn.hs - Expr類型是core的“核心”。 構造函數Cast (Expr b) Coercion表示Cast (Expr b) Coercion

ghc/compiler/types/TycoRep.hs -的定義Coercion在這里。

ghc/compiler/main/HscTypes.hs -的定義ModGuts和字段的“子集” CgGuts用於代碼生成和ModIface / ModDetails用於寫入接口文件和鏈接。

ghc/compiler/main/TidyPgm.hs -功能的定義tidyGuts其中, ModGuts信息被分成CgGuts用於代碼生成和ModDetails ,的高速緩存版本ModIface編譯多個模塊時保存在存儲器和/或用於產生一個完整的ModIface寫入接口文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM