如何使用属于类型 class 的组件创建一个元组实例 II

How to make a tuple with components belonging to a type class an instance II

这是对几分钟前刚提出的问题的修改 - 但对于这种情况,我遇到了问题...

我有以下问题:我定义了一个类型 class 并想将此 class 类型的元组也声明为实例。但我不知道如何让 GHC 接受这个声明。这里有一个非常简单的例子:

class Test x a where
    elm :: a

知道元组我想做类似

的事情
instance (Test x a, Test x b) => Test x (a,b) where
    elm = (elm, elm)

此外,我正在使用

{-# LANGUAGE MultiParamTypeClasses      #-}
{-# LANGUAGE FlexibleInstances          #-}

添加类型 x 导致这里出现问题... 这是怎么做到的?在此先感谢您的任何建议!

这与元组无关。问题很简单,x 出现在 class 头部,而不是 elm 的签名——所以没有办法确定使用什么作为 x 类型,当elm 出现在您的代码中。

确实,如果 elmTest 的唯一方法,那么根本不需要那个 x 参数——只需删除它,您的实例就可以了:

class Test a where
  elm :: a
instance (Test a, Test b) => Test (a,b) where
  elm = (elm, elm)

更有可能的是,您实际上有一些其他方法确实使用了 x,例如

class Test x a where
  elm :: a
  beech :: x -> a

在这种情况下,将 elm 分解为更简单的 superclass:

可能有意义
class PreTest a where
  elm :: a
class (PreTest a) => Test x a where
  beech :: x -> a

或者,您可以通过其他方式获取 x 信息,而不是通过方法的签名。这可以通过基金来完成:

{-# LANGUAGE FunctionalDependencies #-}
class Test x a | a->x where
  elm :: a

这表明任何类型 a 只能有一个 Test _ a 实例,因此编译器可以从中明确地推断出 x

但我严重怀疑您并不真的想要那个——这样的 class 比完整的双参数 class 灵活得多。现代 Haskell 倾向于支持基本等效的关联类型同义词而不是 fundep MultiParamTypeClasses,并且在 xa 实际上是两个独立参数时主要使用 MTPC。