Difference between revisions of "Ru/GHC/Class Instance Extensions"
m |
|||
(2 intermediate revisions by one other user not shown) | |||
Line 1: | Line 1: | ||
⚫ | |||
− | |||
==-XConstrainedClassMethods== |
==-XConstrainedClassMethods== |
||
Line 83: | Line 81: | ||
Здесь тип tailsObsEq :: (ObservableEq [a]) => [a] -> [a] -> Bool, т.е. был применён второй instance. Если мы выключим ключик IncoherentInstances, то поимеем ошибку при сравнении tailsObsEq [1] [1], т.к. это уже тип [Integer]. IncoherentInstances же закрепляет за tailsObsEq навсегда второй инстанс. |
Здесь тип tailsObsEq :: (ObservableEq [a]) => [a] -> [a] -> Bool, т.е. был применён второй instance. Если мы выключим ключик IncoherentInstances, то поимеем ошибку при сравнении tailsObsEq [1] [1], т.к. это уже тип [Integer]. IncoherentInstances же закрепляет за tailsObsEq навсегда второй инстанс. |
||
+ | |||
+ | [[Category:Ru]] |
||
⚫ | |||
+ | [[Category:Language extensions]] |
Latest revision as of 23:05, 29 June 2021
-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.
-XUndecidableInstances
Аналог синонимов типов. Синонимы класса. Применяется совместно с FlexibleInstances.
Пример
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
class ObservableEq a where
(===) :: a -> a -> Bool
instance Eq a => ObservableEq a where
(===) = (==)
Экземпляр класса здесь представляет не конкретный тип, а (Eq a) => a.
-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 не будет ругаться, а выберет более точный инстанс (в нашем случае последний).
-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 навсегда второй инстанс.