Про свободные теоремы
Jan. 22nd, 2012 05:34 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Свободная теорема - это содержательное тождество, которое следует из типа любой параметрически полиморфной функции в полиморфно типизированном лямбда-исчислении. В "простых" полиморфных системах (вроде System F) свободные теоремы выполняются безусловно. В более богатых системах, например, в Хаскелле, имеются некоторые ограничения, возникающие из-за наличия в языке примитивов неограниченной рекурсии fix и строго вычисления seq, подробности см. [Johann06].
Свободная теорема для любой полиморфной функции с типом
Свободная теорема для
Можно записать и более общую версию этой теоремы, годную для произвольных функторов. Возьмём
В качестве примера можно привести функцию maybeToList. Она имеет тип Maybe a -> [a], что даёт свободную теорему
Свободные теоремы полезно записывать в бесточечном стиле - это позволяет глубже проникнуть в их естество:) Первый шаг на этом пути для случая с двумя произвольными функторами очевиден - избавиться от экземпляра x функтора fl a. Это даст
Определим наиболее общие типы левой и правой частей последней версии нашей свободной теоремы. В стандартном контексте g :: a -> b имеем
Несколько упражнений.
Проверьте, что для указанных типов имеют место приведённые свободные теоремы. Выведите "грамотно унифицированный" тип обеих частей равенства.
PS. Ну и чтобы всё было в одном месте - автоматический генератор свободных теорем.
Свободная теорема для любой полиморфной функции с типом
t :: [a] -> [a]имеет вид
map g (t xs) == t (map g xs)где g - совершенно произвольная функция, а xs - список, передаваемый в t в качестве аргумента. Например, взяв в качестве t функцию tail, в качестве g функцию succ, а в качестве xs список [1,2,3,4], получим
map succ (tail [1,2,3,4]) == map succ [2,3,4] == [3,4,5] tail (map succ [1,2,3,4]) == tail [2,3,4,5] == [3,4,5]
Свободная теорема для
t :: [a] -> [a]может быть получена из коммутативности квадрата
t [a] --> [a] a | | | map g| |map g |g v v v [b] --> [b] b tЗдесь g :: a -> b, а t, как параметрически полиморфная функция, может действовать на список любого типа: хоть [a], хоть [b]. Коммутативность таких квадратов есть следствие теоремы параметричности [Reynolds83], [Wadler89], [Johann06]. В терминах теории категорий полиморфная функция t - это естественное преобразование функтора списка в функтор списка.
Можно записать и более общую версию этой теоремы, годную для произвольных функторов. Возьмём
t :: Functor fl, Functor fr => fl a -> fr aтогда квадрат
t fl a --> fr a a | | | fmapl g| |fmapr g |g v v v fl b --> fr b b tдаст свободную теорему
fmapr g (t x) == t (fmapl g x)(Хотя в Хаскелле можно было бы использовать универсальное имя fmap для класса типов Functor, удобнее различать поведение разных функторов - отсюда обозначения fmapl и fmapr.)
В качестве примера можно привести функцию maybeToList. Она имеет тип Maybe a -> [a], что даёт свободную теорему
map g (maybeToList mv) == maybeToList (fmap g mv)Взяв в качестве g функцию succ, а в качестве mv величину, например, Just 41, получим ожидаемый результат и в левой и в правой частях равенства (проверьте это).
Свободные теоремы полезно записывать в бесточечном стиле - это позволяет глубже проникнуть в их естество:) Первый шаг на этом пути для случая с двумя произвольными функторами очевиден - избавиться от экземпляра x функтора fl a. Это даст
fmapr g . t == t . fmapl gСледующий шаг - избавление от t. Для этого воспользуемся сечениями композиции
fmapr g . t ==(fmapr g .) t t . fmapl g == (. fmapl g) tИмеем свободную теорему для типа fl a -> fr a в виде сечений
(fmapr g .) == (. fmapl g)(В качестве упражнения попробуйте избавиться и от g.)
Определим наиболее общие типы левой и правой частей последней версии нашей свободной теоремы. В стандартном контексте g :: a -> b имеем
(fmapr g .) :: Functor fr => (d -> fr a) -> d -> fr b (. fmapl g) :: Functor fl => (fl b -> e) -> fl a -> eНаивная унификация даст наиболее общий из возможных типов первого ранга
(Functor fl, Functor fr) => (fl b -> fr b) -> fl b -> fr bК сожалению, это не то, что нам нужно: тип g станет окажется менее общим, чем хотелось бы, а именно b -> b. Однако, переходя к типам второго ранга, легко написать нужный нам тип, подходящий для обоих выражений
(fmapr g .) :: (Functor fl, Functor fr) => (forall c . fl c -> fr c) -> fl a -> fr b (. fmapl g) :: (Functor fl, Functor fr) => (forall c . fl c -> fr c) -> fl a -> fr b
Несколько упражнений.
Проверьте, что для указанных типов имеют место приведённые свободные теоремы. Выведите "грамотно унифицированный" тип обеих частей равенства.
[[a]] -> [a] (map g .) == ( . map (map g)) (Functor flo, Functor fli, Functor fr) => flo (fli a) -> fr a (fmapr g .) == ( . fmaplo (fmapli g)) [a] -> [a] -> [a] ((map g .) .) == ((. map g) .) . (. map g) (Functor fl, Functor fc, Functor fr) => fl a -> fc a -> fr a ((fmapr g .) .) == ((. fmapc g) .) . (. fmapl g)Здесь g :: a -> b - совершенно произвольная функция, а fmapXXX - это fmap для функтора fXXX.
PS. Ну и чтобы всё было в одном месте - автоматический генератор свободных теорем.
no subject
Date: 2012-01-22 01:42 pm (UTC)Разве "free" в "free theorems" не употребляется в смысле "бесплатные"? (Хотя "бесплатные теоремы" тоже звучит странно.)
no subject
Date: 2012-01-22 01:45 pm (UTC)no subject
Date: 2012-01-22 04:31 pm (UTC)Т.е. свободны от нелогических аксиом.
осторожно, текст выше может не нести никакого смысла
no subject
Date: 2012-01-22 07:00 pm (UTC)У Вадлера в abstract говорится "This provides a free source of useful theorems [...]", так что, видимо, это и есть обоснование названия free.
no subject
Date: 2012-01-24 06:29 am (UTC)Естественное_преобразование
no subject
Date: 2012-01-31 03:07 pm (UTC)no subject
Date: 2012-02-02 08:20 pm (UTC)no subject
Date: 2012-02-02 08:24 pm (UTC)