Добавление кортежей в 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нет. Это означает:

  • Вы не можете назначать какие-либо переменные / функции

  • Вы не можете использовать лямбды

  • Вы не можете импортировать

Вот тот же вопрос, когда это была CMC


9
Я никогда не понимал, почему это называется « без очков », когда оно на самом деле полно очков. : P
Mr. 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]короче.
Орджан Йохансен

К сожалению, mapM idэто версия функции для гольфа, которую вы, вероятно, ищете sequence.
Орджан Йохансен

Да, это правда. Я просто смотрю на (<*>)подпись, которая есть m (a → b) → m a → m b. Так близко ...
полностью человек

1
Есть также Control.Lens.??, что, возможно , было предложено для включения в базу в какой-то момент.
Эрджан Йохансен

Я хочу извлечь повторяющееся (.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- кортежей очень похожа на реализацию из Either(из base-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это так многословно. :( Но вы можете заменить крайние скобки на $.
Орджан Йохансен

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