Haskell 基于类约束的Fire重写规则

Haskell 基于类约束的Fire重写规则,haskell,Haskell,我正在尝试编写一个maybeShow函数,它是show,但没有show类约束。以下是我的尝试: {-# INLINE [1] maybeShow #-} maybeShow :: a -> Maybe String maybeShow _ = Nothing canShow :: Show a => a -> Maybe String canShow = Just . show data CantShow = CantShow main = do print (may

我正在尝试编写一个
maybeShow
函数,它是
show
,但没有
show
类约束。以下是我的尝试:

{-# INLINE [1] maybeShow #-}
maybeShow :: a -> Maybe String
maybeShow _ = Nothing

canShow :: Show a => a -> Maybe String
canShow = Just . show

data CantShow = CantShow

main = do
  print (maybeShow (42 :: Int))
  print (maybeShow CantShow)

{-# RULES
"maybeShow" forall (x :: (Show a => a)). maybeShow x = canShow x
#-}
但在这段代码中,重写规则似乎从未启动过

我知道对于可显示的类型,有时会返回
Nothing
。例如,我完全希望在非内联函数中使用
maybeShow
,而这些函数不是专门针对特定类型的函数,可以返回
Nothing
。但是,当我使用
maybeShow
作为添加到
error
输出中的内容时,如果它不总是起作用,这其实并不重要

但我希望它有时能工作(例如,当它被内联到调用函数中时),而不是像现在这样永远不能工作


关于如何启动重写规则有什么想法吗?这表明它是可以做到的,但是这个建议可以追溯到GHC 6.6,所以我不确定它是否仍然有效。

我仍然不清楚这些要求,但除了以下两个,我想不出其他解决方案,例如,通过跟踪参数类型的跟踪值来调试多态函数库,但添加
Show
约束将破坏下游代码


对单态类型使用重写规则。我假设出于调试目的,您只需要几个类型。然而,这可能相当不可靠,您可能需要明确地专门化/内联函数


也许您可以使用另一个类型类和一个可重叠的实例

class MaybeShow a where
  maybeShow :: a -> Maybe String

instance {-# OVERLAPPABLE #-} MaybeShow a where
  maybeShow _ = Nothing
然后有选择地将其专门化为用于调试的少数类型

instance MaybeShow Int where
  maybeShow n = Just (show n)
但是,您仍然需要为使用它的每个函数添加一个
MaybeShow
约束

在这里,您可以经常使用
PartialTypeSignatures
编写更简洁的顶级签名

myFun :: _ => a -> w a
constrainedFun :: (_, RealConstraint a) => a -> b a

但是,这种方法的优点是行为更加可预测。

我认为您不能有条件地对实例的存在触发规则,因为正如您链接到的页面所示,规则在字典展开后应用,然后变成简单的语法检查。你能解释一下你想做什么吗?显示变量以进行调试(即在“错误”调用中),而不需要显示约束。