deniok: (typed lambda)
[personal profile] deniok
На RSDN nikov последнее время пишет в point-free стиле на стероидах, используя конструкции имеющие "довольно ясный интуитивный смысл (c)". Типа
fpower = (appEndo.).(mconcat.).(.Endo).replicate
Поскольку я когда-то взвалил на себя ношу по несению point-free стиля в массы, придется писать мини-туториал.



Конструкция (. f) . g
\f g -> (. f) . g :: (d -> b) -> (a -> b -> c) -> (a -> d -> c)
Конструкция (. f) . g порождает функцию, эквивалентную g, только её второй аргумент вместо явной передачи заменен на результат вызова f.
g         :: a -> b -> c
f         :: d -> b
тогда
(. f) . g :: a -> d -> c
Диаграммой:
     d
    f|
     v
a -> b -> c
     g
В виде вызовов (с типами):
(g x::a (f z::d)::b)::c
Примеры:
-- перед отображением берем хвост списка
(. tail) . map
-- перед зиповкой увеличиваем элементы первого списка на 1
(. map succ) . zipWith
--перед свёрткой фильтруем список
(. filter (>3)) . foldr1
-- point-free определение replicate
(. repeat) . take


Конструкция (f .) . g
\f g -> (f .) . g :: (c -> d) -> (a -> b -> c) -> (a -> b -> d)
Конструкция (f .) . g порождает функцию, эквивалентную g, только её результат обрабатывается затем f.
g         :: a -> b -> c
f         :: d -> b
тогда
(f .) . g :: a -> b -> d
Диаграммой:
     g
a -> b -> c
          |f
          v
          d
В виде вызовов (с типами):
(f (g x::a y::b)::c)::d
Примеры:
-- point-free определение takeWhile
(fst .) . span
-- point-free определение mapM
(sequence .) . map
-- возвращает 0 при неудачном поиске
(fromMaybe 0 .) . find



Конструкция g . (f .)
\f g -> g . (f .) :: (d -> b) -> ((a -> b) -> c) -> ((a -> d) -> c)
Конструкция g . (f .) порождает функцию, эквивалентную g, только вместо ее функционального аргумента передается композиция f и нового функционального аргумента.
g         :: (a -> b) -> c
f         ::  d -> b
тогда
g . (f .) :: (a -> d) -> c
Диаграммой:
      d
     f|
      v
(a -> b) -> c
     g
В виде вызовов (с типами):
(g (f::d->b . h::a->d)::a->b)::c
Пример:
-- при отображении к передаваемой функции 
-- спереди прикомпозируется преобразование digitToInt
map . (digitToInt .)
-- при проверке видно, что succ вызывается 
-- до преобразования к Int (вылет на digitToInt 'G')
> (map . (digitToInt .)) succ "ABCDE"
[11,12,13,14,15]
> (map . (digitToInt .)) succ "ABCDEF"
[11,12,13,14,15,*** Exception: Char.digitToInt: not a digit 'G'



Конструкция g . (. f)
\f g -> g . (. f) :: (a -> d) -> ((a -> b) -> c) -> ((d -> b) -> c)
Конструкция g . (. f) порождает функцию, эквивалентную g, только вместо ее функционального аргумента передается композиция нового функционального аргумента и f.
g         :: (a -> b) -> c
f         ::  a -> d
тогда
g . (. f) :: (d -> b) -> c
Диаграммой:
     g
(a -> b) -> c
 |f
 v
 d
В виде вызовов (с типами):
(g (h::d->b . f::a->d)::a->b)::c
Пример:
-- при отображении к передаваемой функции 
-- сзади прикомпозируется преобразование digitToInt
map . (. digitToInt)
-- при проверке видно, что succ вызывается 
-- после преобразования к Int (нет вылета в отличие от прошлого примера)
> (map . (.digitToInt)) succ "ABCDE"
[11,12,13,14,15]
> (map . (.digitToInt)) succ "ABCDEF"
[11,12,13,14,15,16]


Date: 2009-10-16 05:14 pm (UTC)
From: [identity profile] kodt-rsdn.livejournal.com
Проще было бы устроить раскрой брюк!
(((f.).g) x) y = (f.) (g x) y = (f.(g x)) y = f (g x y)
(((.f).g) x) y = (.f) (g x) y = ((g x).f) y = (g x) (f y)
((f.(g.)) x) y = f (g.x) y
((f.(.g)) x) y = f (x.g) y

Мне кажется, что можно пойти с другой стороны:
1) перечислить все формулы из 4 термов, из которых 2 связаны - и найти point-free записи для них
2) выучить самые расхожие формулы
3) в качестве образца расхожести можно взять вилки-ложки-крючочки из J

f g x y = (f g) x y
f g (x y) = ((f g).x) y = ((f g).) x y
f (g x) y = (f.g) x y
f (g x y) = (f.(g x)) y = ((f.).g) x y
f (g (x y)) = (f.(g.x)) y = ((f.).(g.)) x y

f x g y = (f x $ g) y = ($g) (f x) y = (($g).f) x y
f x (g y) = (f x . g) y = ((.g).f) x y
f (x g) y = f (x $ g) y = (f.($g)) x y
f (x g y) = ((f.)(x $ g)) y = ((f.).($g)) x y
f (x (g y)) = (f.x.g) y = ((f.).(.g)) x y

и т.д.
Очень несложно наловчиться - и рожать point-free с сечениями, и восстанавливать.

Date: 2009-10-16 06:43 pm (UTC)
From: [identity profile] deni-ok.livejournal.com
> выучить самые расхожие формулы
Их слишком много, чтобы просто учить. Нужно порциями, да с примерами, иначе не запоминаются (у меня, по крайней мере).

Вот, скажем, логическая порция: тройная композиция унарных функций (f и g -- связанные функции, h -- свободная функция, x -- свободный аргумент):
f (g (h x)) = (f . (g . h)) x = ((f .) ((g .) h)) x = ((f .) . (g .)) h x

f (h (g x)) = (f . (h . g)) x = ((f .) ((. g) h)) x = ((f .) . (. g)) h x
f (h (g x)) = ((f . h) . g) x = ((. g) ((f .) h)) x = ((. g) . (f .)) h x

h (f (g x)) = ((h . f) . g) x = ((. g) ((. f) h)) x = ((. g) . (. f)) h x
Примеры (разумные) не придумываются :)

Profile

deniok: (Default)
deniok

February 2022

S M T W T F S
  12345
6789101112
13141516171819
20212223 242526
2728     

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 25th, 2025 03:47 pm
Powered by Dreamwidth Studios