lomeo: (лямбда)
[personal profile] lomeo
Расширения типа fundep или MPTC обычно понятны бывают сразу, ну, по крайней мере, их идея. А вот чтобы разобраться с ошибками при инстанциировании класса, придётся разобраться.


-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 ещё до тонкостей не понимаю.

Date: 2008-07-30 05:37 am (UTC)
From: [identity profile] nivanych.livejournal.com
Афтар тоже сомневается.
Но до сих пор не убрал этот suggestion.
И я тоже сомневаюсь, поэтому и спрашиваю :-)

Profile

lomeo: (Default)
Dmitry Antonyuk

April 2024

S M T W T F S
 123456
7891011 1213
14151617181920
21222324252627
282930    

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 9th, 2025 09:21 pm
Powered by Dreamwidth Studios