带有“虚拟”参数的类型类方法

G. *_*ues 6 haskell

类型类Data. Bits有一个方法,如果参数的类型是有符号类型,isSigned :: a -> Bool则返回该方法。True文档明确指出该参数被忽略。类型类中还有其他类似的方法;还有其他类型类也具有此类方法。我的问题:为什么选择这样的设计?该值仅取决于类型,所以为什么不只是:

isSigned :: Bool
Run Code Online (Sandbox Code Playgroud)

作为后续:假设我有一个带有 nullary method 的自定义类型类method :: Bool。是否有任何理由改变它并这样做Data.Bits,即method :: a -> Bool

che*_*ner 6

简而言之,该参数在运行时被忽略时被忽略,但在编译期间使用参数的类型来选择要isSigned在运行时使用的正确实例。

\n
\n

如果没有参数,就无法确定应该使用哪个实例来解析类似的值isSigned :: Bool

\n
> class Foo a where isSigned :: Bool\n\n<interactive>:1:19: error:\n    \xe2\x80\xa2 Could not deduce (Foo a0)\n      from the context: Foo a\n        bound by the type signature for:\n                   isSigned :: forall a. Foo a => Bool\n        at <interactive>:1:19-34\n      The type variable \xe2\x80\x98a0\xe2\x80\x99 is ambiguous\n    \xe2\x80\xa2 In the ambiguity check for \xe2\x80\x98isSigned\xe2\x80\x99\n      To defer the ambiguity check to use sites, enable AllowAmbiguousTypes\n      When checking the class method: isSigned :: forall a. Foo a => Bool\n      In the class declaration for \xe2\x80\x98Foo\xe2\x80\x99\n
Run Code Online (Sandbox Code Playgroud)\n

如果启用TypeApplicationsAllowAmbiguousTypes扩展,您可以执行以下操作:

\n
class Foo a where\n    isSigned :: Bool\n\ninstance Foo Int where\n    isSigned = True\n\ninstance Foo Char where\n    isSigned = False\n
Run Code Online (Sandbox Code Playgroud)\n

单独使用isSigned仍然会出现错误,但您可以使用isSigned @IntorisSigned @Char来获取给定类型的特定值。

\n

回到标准 Haskell,我们需要某种方法来选择isSigned需要哪个实例的值,我们通过定义一个函数来实现这一点,该函数的参数类型将其与特定实例联系起来。参数的被忽略,但在类型检查和编译期间使用类型来选择正确的实例。

\n

  • 也许提到[“在术语类型中对所有人可见”提案](https://ghc-proposals.readthedocs.io/en/latest/proposals/0281-visible-forall.html)也会很有趣,该提案[将成为 GHC 9.10 的一部分](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/9.10.1-notes.html)。这消除了对不明确类型的需要,并强制显式应用该类型。 (5认同)