Dodanie krotki w trybie pointfree

16

Jaki jest najkrótszy sposób na wyrażenie funkcji

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

w notacji bez punktów?

pointfree.io daje nam

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

które przy odrobinie pracy można skrócić

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

dla 76 bajtów. Ale wciąż wydaje się to naprawdę długie i skomplikowane jak na tak proste zadanie. Czy jest jakiś sposób, aby wyrazić dodawanie parami jako krótszą funkcję bez punktów?

Aby wyjaśnić, co mam na myśli przez określenie „bez punktów”, deklaracja funkcji bez punktów obejmuje przejęcie istniejących funkcji i operatorów i zastosowanie ich względem siebie w taki sposób, aby utworzyć żądaną funkcję. Backticks, nawiasy i wartości literalne ( [], 0, [1..3], itd) są dozwolone, ale słowa kluczowe, jak wherei letnie. To znaczy:

  • Nie możesz przypisywać żadnych zmiennych / funkcji

  • Nie możesz używać lambdas

  • Nie możesz importować

Oto to samo pytanie, kiedy było to CMC

Post Rock Garf Hunter
źródło
9
Nigdy nie zrozumiałem, dlaczego nazywa się to „ bez punktów ”, skoro jest tak naprawdę pełne punktów. : P
Mr. Xcoder,
5
Szkoda, że ​​nie wolno nam importować najlepszego pakietu Haskell , bo inaczej rozwiązanie byłoby po prostu (+)***(+).
Silvio Mayolo,
2
Pomysł: (+)<$>([1],2)<*>([3],4)daje ([1,3],6).
xnor
2
Spędziłem trochę czasu, próbując stworzyć dobre rozwiązanie z wykorzystaniem końcówki xnor ... ale skończyłem z tymi śmieciami . Nie wiem nawet, dlaczego czasami próbuję ...
totalnie ludzki,

Odpowiedzi:

11

44 bajty

Mam to od \x y -> (fst x + fst y, snd x + snd y)

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

Wypróbuj online!

H.PWiz
źródło
8

44 bajty

-8 bajtów dzięki Ørjan Johansen. -3 bajty dzięki Bruce Forte.

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

Wypróbuj online!

Przetłumaczyć na:

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

67 bajtów

-8 bajtów dzięki Ørjan Johansen. -1 bajt dzięki Bruce Forte.

Jeśli wymagane jest wyjście krotki:

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

Wypróbuj online!

Tak, ręcznie to robię, nie produkując dojrzałych owoców. Ale cieszę się z [a] → (a, a)nawrócenia.

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

Teraz jeśli jest krótka funkcja z m (a → b) → a → m b.

całkowicie ludzki
źródło
3
Nienawidzę cię łamać, ale mapM id[fst,snd]jest krótszy.
Ørjan Johansen
Niestety, mapM idjest to gra w golfa , której prawdopodobnie szukasz sequence.
Ørjan Johansen
Tak to prawda. Patrzę tylko na (<*>)podpis, który jest m (a → b) → m a → m b. Tak blisko ...
całkowicie ludzki,
1
Są też Control.Lens.??, które w pewnym momencie mogły zostać zaproponowane do włączenia do bazy.
Ørjan Johansen
Chcę, aby wyodrębnić powtarzające się (.mapM id[fst,snd])jak let r=(.mapM id[fst,snd]) in r(r.zipWith(+)), ale nie byłem w stanie uzyskać typechecker przyjąć wersję pointfree.
xnor
4

54 bajty

Szczerze wątpię, że pokonamy 44 bajtowe rozwiązanie H.PWiz, ale nikt nie używał faktu, że (,)implementuje klasę typów Functor, więc oto kolejna interesująca, która nie jest taka zła:

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

Wypróbuj online!

Wyjaśnienie

Implementacja klasy typu Functordla 2- krotek jest bardzo podobna do Either(z 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)

Dla tego wyzwania oznacza to, że następująca funkcja dodaje drugie elementy, zachowując pierwszy element drugiego argumentu:

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

Gdybyśmy tylko mieli małego pomocnika helpPlz = \a b -> (fst a+fst b,snd b), moglibyśmy to (helpPlz<*>).flip(fmap.(+).snd)zrobić. Na szczęście mamy narzędzie, pointfreektóre daje nam:

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

Po ponownym podłączeniu tej funkcji dochodzimy do powyższego rozwiązania (zwróć uwagę na to, (<*>) = apco jest w bazie ).

ბიმო
źródło
4

60 bajtów

Nie widzę uncurrytu żadnej miłości, więc pomyślałem, że wpadnę i to naprawię.

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

Myślałem, ze wszystkie wymienione fsti snd, że rozpakowaniu argumenty uncurrymogłyby uzyskując pewne rezultaty. Najwyraźniej nie było tak owocne, jak się spodziewałem.

Silvio Mayolo
źródło
2
uncurryjest taki pełny. :( Ale możesz zastąpić nawiasy najbardziej zewnętrzne $.
Ørjan Johansen
Tak, i to niestety problem z wieloma nazwami funkcji w Haskell. Po prostu za długo na golfa. Ale dziękuję za oszczędności 1 postaci!
Silvio Mayolo,