触发类约束的重写规则

时间:2017-03-29 04:26:16

标签: 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 (maybeShow (42 :: Int))
  print (maybeShow CantShow)

{-# RULES
"maybeShow" forall (x :: (Show a => a)). maybeShow x = canShow x
#-}

但是在这段代码中,重写规则似乎永远不会触发。

我知道有时会为可显示的类型返回Nothing。例如,我完全希望在非内联函数中使用maybeShow而不是特定类型的函数返回Nothing。但是,当我使用maybeShow作为添加到error输出的内容时,如果它不能始终有效,那么它并不重要。

但我希望它有时可以工作(例如,当它被内联到调用函数中时),而不是现在似乎没有。

有关如何启动重写规则的任何想法? wiki.haskell.org上的这个建议可以做到,但建议可以追溯到GHC 6.6,所以我不确定它是否仍然有效。

1 个答案:

答案 0 :(得分:0)

我的要求仍然不明确,但我无法想到其他解决方案而不是以下两个解决方案,例如,通过跟踪参数类型的跟踪值调试多态函数库,但添加{{1约束会破坏下游代码。

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

也许你可以使用另一个带有覆盖可覆盖实例的类型。

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

然而,这种方法具有更具可预测性的优点。