Wen przy użyciu zależności funkcjonalnych, często uderzam w stan pokrycia . Można go podnieść za pomocą UndecidableInstances
, ale zwykle staram się trzymać z daleka od tego przedłużenia.Jak obejść warunki pokrycia dla zależności funkcjonalnych bez użycia -XUndecidableInstances
Oto nieco wymyślony przykład, że działa bez 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
Kiedy robię typ wynik bardziej uniwersalne, pokrycie Stan awarii (stąd wymagające 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 uważam, że ponieważ b
i c
są określone przez a
, bardziej ogólny kod nie powinien powodować żadnych problemów, więc moje pytania:
- Czy istnieją ewentualne problemy z użyciem
UndecidableInstances
tutaj - mogę modelować powyższy scenariusz bez polegania na
UndecidableInstances
(być może z rodzinami typu?)
Nie ma żadnego powodu, aby unikać "UndecidableInstances". Najgorsze, co może się zdarzyć, to, że sprawdzanie typu zaczyna się zapętlać (i mówię o tym, jak sądzę). Możesz sprawić, że warunki zasięgu będą coraz bardziej sprytne, ale nigdy nie zrobią wszystkiego, co chcesz, ponieważ jest to nierozstrzygalne. – augustss
jak jest określona przez a tutaj? – Saizan