haskell 隐藏GHC基本库以防止模式匹配从整数使用中取消对GHC.Num的糖

fnatzsnv  于 2023-01-21  发布在  其他
关注(0)|答案(1)|浏览(134)

我已经创建了一个替代的Prelude,用于教授Haskell的初学者,名为FirstPrelude。目标之一是从标准库中删除类型类,以便错误消息更像是经典的Hindley-Milner类型,而不是No instance错误。这非常有效。但是,我没有预料到的是,当模式匹配时,GHC绕过了我对fromInteger的重新定义(定义为恒等式,单态化为只对Integer有效),因此,例如,使用以下函数:

isZero 0 = True
isZero _ = False

如果我问GHCi类型,我得到:

isZero :: (GHC.Classes.Eq a, GHC.Num.Num a) => a -> Bool

但是我想要的是得到Integer -> Bool。从GHC中转储简化的核心,我可以看到它使用:

(GHC.Num.fromInteger @Integer GHC.Num.$fNumInteger 0)))

我本以为它只会使用我的fromInteger :: Integer -> Integer,但可惜没有。有什么方法可以阻止GHC.Num.fromInteger被使用吗?我想这在包级别上可能是可能的,但出于其他教学原因,我真的希望在模块级别上这样做。

lpwwtiir

lpwwtiir1#

这与模式匹配无关:在Example.hs中,表达式中的文字也是多态的。

simpler :: ()
simpler = 1

并观察错误消息

[2 of 2] Compiling Main             ( Example.hs, interpreted )

Example.hs:7:11: error:
    • No instance for (GHC.Num.Num ()) arising from the literal ‘1’
    • In the expression: 1
      In an equation for ‘simpler’: simpler = 1
  |
7 | simpler = 1
  |           ^
Failed, one module loaded.

您可能没有注意到,因为只要您使用“您的”操作之一,GHC就会专门化该类型,并且对于顶级值可能使用默认值。
但是注意

simpler _ = 1

它会推断出这种类型

ghci> :t simpler
simpler :: GHC.Num.Num p1 => p2 -> p1

如果你启用了{-# LANGUAGE RebindableSyntax #-},它就真的使用了你的fromInteger,一切都如你所愿。你可以在.cabal文件中这样做,也许足够满足你的教育需求了。

相关问题