Ru/GHC/Class Instance Extensions
From HaskellWiki
Contents |
1 -XConstrainedClassMethods
Позволяет определять контекст над переменными типа из объявления класса в объявлениях методов. Частичная задача -XFlexibleContexts.
Пример
{-# LANGUAGE MultiParamTypeClasses, ConstrainedClassMethods #-} class Map m k v where empty :: m k v put :: k -> v -> m k v -> m k v get :: Eq k => k -> m k v -> Maybe v
Здесь в get определён контекст для k.
2 -XUndecidableInstances
Аналог синонимов типов. Синонимы класса. Применяется совместно с FlexibleInstances.
Пример
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} class ObservableEq a where (===) :: a -> a -> Bool instance Eq a => ObservableEq a where (===) = (==)
Экземпляр класса здесь представляет не конкретный тип, а (Eq a) => a.
3 -XOverlappingInstances
С предыдущей опцией можно наворотить кучу инстансов, которые могут быть применимы к одному и тому же набору типов.
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances #-} class ObservableEq a where (===) :: a -> a -> Bool instance Eq a => ObservableEq a where (===) = (==) instance ObservableEq [a] where (x:xs) === (y:ys) = True _ === _ = False
И вот мы применяем (===) к [Int]. Какой инстанс сработает?
При включении флага OverlappingInstances GHC не будет ругаться, а выберет более точный инстанс (в нашем случае последний).
4 -XIncoherentInstances
Пойдём дальше, предположим, что некой функции мы выбрали наиболее точный инстанс, однако эта функция может примениться к типу, для которого подходит ещё более точный инстанс. Код:
{-# LANGUAGE FlexibleInstances, UndecidableInstances, OverlappingInstances, IncoherentInstances #-} class ObservableEq a where (===) :: a -> a -> Bool instance Eq a => ObservableEq a where (===) = (==) instance ObservableEq [a] where (===) = undefined instance ObservableEq [Integer] where (===) = (==) tailsObsEq xs ys = tail xs === tail ys
Здесь тип tailsObsEq :: (ObservableEq [a]) => [a] -> [a] -> Bool, т.е. был применён второй instance. Если мы выключим ключик IncoherentInstances, то поимеем ошибку при сравнении tailsObsEq [1] [1], т.к. это уже тип [Integer]. IncoherentInstances же закрепляет за tailsObsEq навсегда второй инстанс.
Categories: Ru | GHC | Extensions
