在過載函式上使用重寫規則
在這個問題中 ,@ 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
等)。
但是,通過首先將 toList
和 fromList
重寫為非內聯非型別類方法,我們可以保護它們免於過早重寫 ,並保留它們直到組合規則可以觸發:
{-# 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