Додавання кортежу в pointfree


16

Який найкоротший спосіб ми можемо виразити функцію

f(a,b)(c,d)=(a+c,b+d)

у точковій нотації?

pointfree.io дає нам

uncurry (flip flip snd . (ap .) . flip flip fst . ((.) .) . (. (+)) . flip . (((.) . (,)) .) . (+))

які за допомогою трохи роботи можна скоротити

uncurry$(`flip`snd).((<*>).).(`flip`fst).((.).).(.(+)).flip.(((.).(,)).).(+)

за 76 байт. Але це все ще здається дійсно довгим і складним для такого простого завдання. Чи є якийсь спосіб ми можемо висловити парне додавання як більш коротку функцію без точок?

Щоб було зрозуміло, що я маю на увазі під точковою, без точкової декларації функції передбачає взяття існуючих функцій та операторів та застосування їх один до одного таким чином, що створюється потрібна функція. Зворотні лапки, дужки і буквальні значення ( [], 0, [1..3]і т.д.) допускається , але ключові слова , як whereі letнемає. Це означає:

  • Ви не можете призначити будь-які змінні / функції

  • Ви не можете використовувати лямбда

  • Ви не можете імпортувати

Ось те саме питання, коли це був КМЦ


9
Я ніколи не розумів , чому він називається «точково безкоштовно » , коли це насправді сповнена точок. : P
Містер Xcoder


5
Прикро, що нам не дозволено імпортувати найкращий пакет Haskell , інакше рішення просто було б (+)***(+).
Сільвіо Майоло

2
Ідея: (+)<$>([1],2)<*>([3],4)дає ([1,3],6).
xnor

2
Я витратив деякий час, намагаючись розробити прекрасне рішення, використовуючи підказки xnor ... але я закінчився цим сміттям . Навіть не знаю, чому я намагаюся іноді ...
зовсімлюдсько

Відповіді:



8

44 байти

-8 байт завдяки Ерджану Йохансену. -3 байти завдяки Брюсу Форте.

(.).flip(.)<*>(zipWith(+).)$mapM id[fst,snd]

Спробуйте в Інтернеті!

Перекладається на:

f t1 t2 = zipWith (+) (mapM id [fst, snd] $ t1) (mapM id [fst, snd] $ t2)

67 байт

-8 байт завдяки Ерджану Йохансену. -1 байт завдяки Брюсу Форте.

Якщо необхідний вихід кортежу:

(((,).head<*>last).).((.).flip(.)<*>(zipWith(+).)$mapM id[fst,snd])

Спробуйте в Інтернеті!

Так, я вручну це не давав стиглих плодів. Але я задоволений [a] → (a, a)наверненням.

listToPair  [a]  (a, a)
listToPair = (,) . head <*> last
-- listToPair [a, b] = (a, b)

Тепер, якщо була коротка функція з m (a → b) → a → m b.


3
Ненавиджу тебе порушити, але mapM id[fst,snd]коротше.
Ørjan Johansen

До жаль, mapM idце golfed версії функції ви , ймовірно , шукаєте, sequence.
Ørjan Johansen

Так, це правда. Я просто дивлюсь на (<*>)підпис, який є m (a → b) → m a → m b. Так близько ...
абсолютнолюдсько

1
Є також Control.Lens.??, які, можливо , були запропоновані включити до бази в якийсь момент.
Ørjan Johansen

Я хочу витягнути (.mapM id[fst,snd])подібне let r=(.mapM id[fst,snd]) in r(r.zipWith(+)), але мені не вдалося змусити машину перевірки набору прийняти точково версію.
xnor

4

54 байти

Я чесно сумніваюся, що ми переможемо рішення 44-х байт @ H.PWiz, але ніхто не використовував той факт, що (,)реалізує клас типу Functor, тому ось ще один цікавий, який не надто поганий:

((<*>snd).((,).).(.fst).(+).fst<*>).flip(fmap.(+).snd)

Спробуйте в Інтернеті!

Пояснення

Реалізація класу типу Functorдля 2 -Tuples дуже схожа на таку Eitherбази-4.10.1.0 ):

instance Functor ((,) a) where
    fmap f (x,y) = (x, f y)

instance Functor (Either a) where
    fmap _ (Left x) = Left x
    fmap f (Right y) = Right (f y)

Що означає це для цього завдання, це те, що наступна функція додає другі елементи, зберігаючи перший елемент другого аргументу:

λ f = fmap.(+).snd :: Num a => (a, a) -> (a, a) -> (a, a)
λ f (1,-2) (3,-4)
(3,-6)

Тож якби ми мали маленьку помічницю, helpPlz = \a b -> (fst a+fst b,snd b)яку б ми могли зробити, (helpPlz<*>).flip(fmap.(+).snd)і ми б це зробили. На щастя, у нас є інструмент, pointfreeякий дає нам:

helpPlz = (`ap` snd) . ((,) .) . (. fst) . (+) . fst

Таким чином, просто включивши цю функцію назад, ми дійшли до вищевказаного рішення (зверніть увагу на те, (<*>) = apщо знаходиться в базі ).


4

60 байт

Я тут не бачу uncurryлюбові, тож я зрозумів, що заскочу і виправлю це.

uncurry$(uncurry.).flip(.)(flip(.).(+)).(flip(.).((,).).(+))

Я вважав, що при всьому fstі snd, що розпакування аргументів uncurryможе дати певні результати. Ясна річ, це було не так плідно, як я сподівався.


2
uncurryтак багатослівний. :( Але ви можете замінити найвіддаленіші дужки $.
Ørjan Johansen

Так, і це, на жаль, проблема з великою кількістю імен функцій в Haskell. Просто занадто довго для гольфу. Але дякую за 1-символьну економію!
Сільвіо Майоло
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.