在重载函数上使用重写规则
在这个问题中 ,@ 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