haskell - 使用 typeclass 方法的默认实现来省略参数

标签 haskell typeclass

我希望能够定义一个(多参数)类型类实例,其类方法的实现忽略其参数之一。这可以很容易地完成如下。

instance MyType MyData () where
    specific _ a = f a

当我在多个地方使用这种模式时,我尝试通过添加一个专门的类方法和足够的默认实现来概括它。我想出了以下内容。

{-# LANGUAGE MultiParamTypeClasses, AllowAmbiguousTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}

class MyType a b where
    specific :: b -> a -> a
    specific = const dontCare
    dontCare :: a -> a
    dontCare = specific (undefined :: b)
    {-# MINIMAL specific | dontCare #-}

然而,这会产生错误 Could not deduce (MyType a b0) arising from a use of ‘dontCare’ [..] The type variable ‘b0’ is ambiguous .我不明白为什么后者应该是类型变量 b 的情况。范围从类签名到方法声明。你能帮我理解这里出现的确切问题吗?

是否有另一种合理的方式来实现我的意图,即以通用方式允许此类修剪实例?

最佳答案

问题出在 specific 的默认定义中。 .让我们缩小一下,看看你的方法实际上是什么类型,基于你的类型签名。

specific :: forall a b. MyType a b => b -> a -> a
dontCare :: forall a b. MyType a b => a -> a

specific 的默认定义中, 你使用 dontCare在类型 a -> a .所以 GHC 推断 dontCare 的第一个类型参数是 a .但是没有什么限制它的第二个类型参数,所以 GHC 无法选择正确的实例字典来使用它。这就是为什么你最终需要 AllowAmbiguousTypes让 GHC 接受 dontCare 的类型签名.这些“模糊”类型在现代 GHC 中有用的原因是我们有 TypeApplications让我们修复它们。这个定义很好用:
class MyType a b where
    specific :: b -> a -> a
    specific = const (dontCare @_ @b)
    dontCare :: a -> a
    dontCare = specific (undefined :: b)
    {-# MINIMAL specific | dontCare #-}

类型应用程序指定第二个参数是 b .您可以填写a对于第一个论点,但 GHC 实际上可以很好地解决这个问题。

关于haskell - 使用 typeclass 方法的默认实现来省略参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62271528/

相关文章:

haskell - OverloadedStrings 语言扩展如何工作?

haskell - 定义一个函数时不使用任何语言扩展,但必须使用语言扩展来声明其类型?

haskell - 为什么我们不能在 Haskell 中为枚举派生 Random 类实例?

monads - Haskell 多参数类型类中的上下文是什么

haskell - 自动将类型签名添加到顶级函数

scala - 如何在 Scala 中编写 Haskell-do-notation

Haskell 模块导入自身

haskell - 如何针对类型类值进行模式匹配?

haskell - ghci 列出所有可能的类型类实例吗?

haskell - 与 Alternative empty 或 Applicative pure 的模式匹配