在使用函数依赖关系时,我经常遇到覆盖条件。使用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
我认为因为b
和c
都是由a
决定的,所以更通用的代码应该不会引起任何问题,所以我的问题是:
- 在这里使用
UndecidableInstances
可能有什么问题吗 - 我可以在不依赖
UndecidableInstances
的情况下对上述场景进行建模吗(可能使用类型族?)
没有什么大理由远离UndecidableInstances
。最糟糕的情况是,类型检查器开始循环(我想告诉你这件事)。你可以让覆盖条件变得越来越巧妙,但它永远不会实现你想要的一切,因为这是不可决定的。