Wen usando dependencias funcionales, con frecuencia llego al Condición de cobertura. Es posible levantarlo con UndecidableInstances
, pero generalmente trato de mantenerme alejado de esa extensión.Cómo evitar la condición de cobertura de las dependencias funcionales sin usar -XUndecidableInstances
Aquí es un ejemplo un tanto artificial, que funciona sin 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
Cuando hago el tipo de resultado más genérico, la condición Cobertura falla (por lo que requieren 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
I pensé que debido a que b
y c
ambos están determinados por a
, el código más genérico no debería causar ningún problema, entonces mis preguntas:
- ¿Hay problemas posibles con el uso de
UndecidableInstances
aquí - ¿Puedo modelar el escenario anterior sin depender de
UndecidableInstances
(tal vez con las familias de tipo?)
No hay una razón importante para mantenerse alejado de 'IndecisoInstancias'. Lo peor que puede pasar es que el verificador de tipos comience a circular (y te cuente sobre ello, creo). Puede hacer que la condición de cobertura sea cada vez más inteligente, pero nunca hará todo lo que pueda desear, ya que eso es indecidible. – augustss
¿cómo se determina c aquí? – Saizan