如何在不使用-XUncidableInstances的情况下绕过函数依赖项的覆盖条件



在使用函数依赖关系时,我经常遇到覆盖条件。使用UndecidableInstances可以提升它,但我通常会尽量远离该扩展。

这里有一个有点做作的例子,它在没有UndecidableInstances:的情况下工作

{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances #-}
data Result = Result String
  deriving (Eq, Show)
data Arguments a b = Arguments a b
class Applyable a b | a -> b where
  apply :: a -> b -> Result
instance Applyable (Arguments a b) (a -> b -> Result) where
  (Arguments a b) `apply` f = f a b

当我使结果类型更通用时,Coverage Condition失败(因此需要UndecidableInstances):

{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}
data Result a = Result a
  deriving (Eq, Show)
data Arguments a b = Arguments a b
class Applyable a b c | a -> b c where
  apply :: a -> b -> Result c
instance Applyable (Arguments a b) (a -> b -> Result c) c where
  (Arguments a b) `apply` f = f a b

我认为因为bc都是由a决定的,所以更通用的代码应该不会引起任何问题,所以我的问题是:

  1. 在这里使用UndecidableInstances可能有什么问题吗
  2. 我可以在不依赖UndecidableInstances的情况下对上述场景进行建模吗(可能使用类型族?)

没有什么大理由远离UndecidableInstances。最糟糕的情况是,类型检查器开始循环(我想告诉你这件事)。你可以让覆盖条件变得越来越巧妙,但它永远不会实现你想要的一切,因为这是不可决定的。

最新更新