![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
На RSDN nikov последнее время пишет в point-free стиле на стероидах, используя конструкции имеющие "довольно ясный интуитивный смысл (c)". Типа
Конструкция (. f) . g
Конструкция (f .) . g
Конструкция g . (f .)
Конструкция g . (. f)
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]
no subject
Date: 2009-10-16 01:29 pm (UTC)no subject
Date: 2009-10-16 01:32 pm (UTC)fxd
no subject
Date: 2009-10-16 05:09 pm (UTC)no subject
Date: 2009-10-16 05:17 pm (UTC)А мне нравится :)
no subject
Date: 2009-10-16 11:27 pm (UTC)no subject
Date: 2009-10-18 06:41 am (UTC)no subject
Date: 2009-10-16 05:14 pm (UTC)(((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 с сечениями, и восстанавливать.
no subject
Date: 2009-10-16 06:43 pm (UTC)Их слишком много, чтобы просто учить. Нужно порциями, да с примерами, иначе не запоминаются (у меня, по крайней мере).
Вот, скажем, логическая порция: тройная композиция унарных функций (f и g -- связанные функции, h -- свободная функция, x -- свободный аргумент):
Примеры (разумные) не придумываются :)
no subject
Date: 2009-10-16 08:37 pm (UTC)С другой -- фан :) Чуть больше примеров -- и уже тянет на статью в fprog или в Monad.Reader.
no subject
Date: 2009-10-17 01:15 am (UTC)no subject
Date: 2009-10-17 03:17 am (UTC)no subject
Date: 2009-10-17 03:24 am (UTC)no subject
Date: 2009-10-17 03:27 am (UTC)no subject
Date: 2009-10-18 09:23 am (UTC)no subject
Date: 2009-10-18 10:26 am (UTC)no subject
Date: 2009-10-18 10:50 am (UTC)На моём маленьком примере работает:
Исходник:
Core:
Как можно видеть, Core-представление обоих функций идентично.
no subject
Date: 2009-10-18 01:36 pm (UTC)no subject
Date: 2009-10-18 09:28 am (UTC)no subject
Date: 2009-10-18 09:29 am (UTC)no subject
Date: 2009-10-18 09:43 am (UTC)MigMit:~ MigMit$ pointfree 'iso (a, (b, c)) = ((a, b), c)'
iso = uncurry ((`ap` snd) . (. fst) . ((,) .) . (,))
no subject
Date: 2009-10-18 10:23 am (UTC)Вопрос в том, где начинается передозняк стероидов
no subject
Date: 2009-10-23 07:23 pm (UTC)обязательно буду на него ссылаться, когда меня будут спрашивать, почему Хаскель нельзя тащить в продакшен (http://lebenliebhaber.livejournal.com/44901.html)
no subject
Date: 2009-10-23 07:39 pm (UTC)Это же чистая алгебра; и полно автоматических средств для "туда-сюда":
Можешь вделать в IDE "преобразовальщик под предпочтительный вид", если есть нужда ;-)
no subject
Date: 2009-10-23 07:43 pm (UTC)но когда я представляю себе встречю с такими штуками в модуле на три тысячи строк, написанном человеком, который пять лет как уволился - меня неиллюзорно бросает в дрожь :-)