双向功能依赖

Sri*_*aic 9 haskell typeclass functional-dependencies type-level-computation

我有一个类型类,看起来有点像以下内容:

class Foo a b | a -> b where
  f :: a -> Bool
  g :: b -> Bool
  h :: a -> b -> Bool
Run Code Online (Sandbox Code Playgroud)

或者至少这些对我的问题很重要。此类没有编译,并且有充分的理由。此类的问题是,我可以(如果愿意)执行以下操作:

instance Foo () Bool where
  f x = True
  g y = y
  h x y = False

instance Foo ((), ()) Bool where
  f x = True
  g y = not y
  h x y = False
Run Code Online (Sandbox Code Playgroud)

现在,如果我打电话g True给每个实例,有两个单独的结果。编译器意识到了这种可能性,并告诉我我的类型类不好。

我的问题是依赖性| a -> b不是我的意思。我不只是意味着你可以找到ab,还以为你能找到ba。也就是说,每种类型都只能Foo与另一种类型成为成员,因此我们可以给一个类型查找另一种类型。或者换一种说法,依赖关系是双向的。这种功能依赖性会阻止我Bool出现在两个单独的实例中,因为第一个参数可以从第二个参数派生,而第二个参数可以从第一个参数派生。

但是我不知道如何向编译器表达这个想法。

如何创建双向功能依赖项?或者,更有可能的是,有一种方法可以重新定义我的类型类,以获取可以替代双向功能依赖项的东西吗?

Wil*_*sem 8

和之间的双向依赖关系可以表示为两个功能依赖关系和,例如:aba -> bb -> a

class Foo a b | a -> b, b -> a where
  f :: a -> Bool
  g :: b -> Bool
  h :: a -> b -> Bool
Run Code Online (Sandbox Code Playgroud)

因此,这里a功能依赖于bb功能依赖于a

instance但是对于您的,这当然会引发错误,因为现在您为定义了两个不同ab ~ Bool。这将引发如下错误:

file.hs:6:10: error:
    Functional dependencies conflict between instance declarations:
      instance Foo () Bool -- Defined at file.hs:6:10
      instance Foo ((), ()) Bool -- Defined at file.hs:11:10
Failed, modules loaded: none.
Run Code Online (Sandbox Code Playgroud)

由于函数依赖的,你只能定义一个ab ~ Bool。但这可能恰恰是您要寻找的东西:一种防止Foo为同一个a或同一个定义两次的机制b