Расширения классов типов. Конспект.
Jul. 29th, 2008 03:54 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Расширения типа fundep или MPTC обычно понятны бывают сразу, ну, по крайней мере, их идея. А вот чтобы разобраться с ошибками при инстанциировании класса, придётся разобраться.
-XConstrainedClassMethods
Позволяет определять контекст над переменными типа из объявления класса в объявлениях методов.
Частичная задача -XFlexibleContexts.
Пример
Здесь в
-XUndecidableInstances
Аналог синонимов типов. Синонимы класса. Применяется совместно с FlexibleInstances.
Пример
Экземпляр класса здесь представляет не конкретный тип, а
-XOverlappingInstances
С предыдущей опцией можно наворотить кучу инстансов, которые могут быть применимы к одному и тому же набору типов.
И вот мы применяем
При включении флага
-XIncoherentInstances
Пойдём дальше, предположим, что некой функции мы выбрали наиболее точный инстанс, однако эта функция может примениться к типу, для которого подходит ещё более точный инстанс. Код:
Здесь тип
На сегодня всё :-) Более общие вещи типа
-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
навсегда второй инстанс.На сегодня всё :-) Более общие вещи типа
FlexibleInstance
ещё до тонкостей не понимаю.
no subject
Date: 2008-07-30 05:37 am (UTC)Но до сих пор не убрал этот suggestion.
И я тоже сомневаюсь, поэтому и спрашиваю :-)