在過載函式上使用重寫規則

在這個問題中 ,@ Virlib 詢問使用重寫規則來利用型別規則來消除一些過載函式呼叫:

請注意以下類:

class ListIsomorphic l where
    toList    :: l a -> [a]
    fromList  :: [a] -> l a

我也要求 toList . fromList == id。如何編寫重寫規則來告訴 GHC 進行替換?

對於 GHC 的重寫規則機制來說,這是一個有點棘手的用例,因為過載的函式被 GHC 在幕後隱式建立的規則重寫為它們的特定例項方法 (所以像 fromList::Seq a -> [a] 這樣的東西會被重寫為 Seq$fromList 等)。

但是,通過首先將 toListfromList 重寫為非內聯非型別類方法,我們可以保護它們免於過早重寫 ,並保留它們直到組合規則可以觸發:

{-# RULES
  "protect toList"   toList = toList';
  "protect fromList" fromList = fromList';
  "fromList/toList"  forall x . fromList' (toList' x) = x; #-}

{-# NOINLINE [0] fromList' #-}
fromList' :: (ListIsomorphic l) => [a] -> l a
fromList' = fromList

{-# NOINLINE [0] toList' #-}
toList' :: (ListIsomorphic l) => l a -> [a]
toList' = toList