Tupelzusatz in pointfree

16

Was ist der kürzeste Weg, um die Funktion auszudrücken

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

in punktloser Notation?

pointfree.io gibt uns

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

was mit ein wenig arbeit gekürzt werden kann

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

für 76 Bytes. Aber für eine so einfache Aufgabe scheint das immer noch sehr lang und komplex zu sein. Gibt es eine Möglichkeit, die paarweise Addition als kürzere punktfreie Funktion auszudrücken?

Um klar zu sein, was ich unter Punktfrei verstehe, bedeutet eine Punktfreie Deklaration einer Funktion, dass vorhandene Funktionen und Operatoren so übernommen und aufeinander angewendet werden, dass die gewünschte Funktion erstellt wird. Backticks, Klammern und Literalwerte ( [], 0, [1..3], usw.) sind erlaubt , aber Schlüsselwörter wie whereund letsind es nicht. Das heisst:

  • Sie dürfen keine Variablen / Funktionen zuweisen

  • Sie dürfen keine Lambdas verwenden

  • Sie dürfen nicht importieren

Hier ist die gleiche Frage, als es ein CMC war

Weizen-Assistent
quelle
9
Ich habe nie verstanden , warum es „punkt- genannt wird frei “ , wenn es tatsächlich ist voll von Punkten. : P
Mr. Xcoder
5
Es ist eine Schande, dass wir nicht das beste Haskell-Paket importieren dürfen , sonst wäre die Lösung einfach (+)***(+).
Silvio Mayolo
2
Eine Idee: (+)<$>([1],2)<*>([3],4)gibt ([1,3],6).
Xnor
2
Ich habe einige Zeit damit verbracht, unter Verwendung von xnors Tipp eine gute Lösung zu finden, aber am Ende habe ich diesen Müll gefunden . Ich weiß nicht mal, warum ich es manchmal versuche ...
totalhuman

Antworten:

8

44 Bytes

-8 Bytes dank Ørjan Johansen. -3 Bytes dank Bruce Forte.

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

Probieren Sie es online!

Wird übersetzt in:

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

67 Bytes

-8 Bytes dank Ørjan Johansen. -1 Byte dank Bruce Forte.

Wenn eine Tupelausgabe erforderlich ist:

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

Probieren Sie es online!

Ja, wenn ich es manuell mache, entstehen keine reifen Früchte. Ich bin aber mit der [a] → (a, a)Umstellung zufrieden .

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

Nun, wenn es eine kurze Funktion mit gab m (a → b) → a → m b.

total menschlich
quelle
3
Ich hasse es, es dir zu brechen, aber es mapM id[fst,snd]ist kürzer.
Ørjan Johansen
Leider mapM idist die golfed Version der Funktion sind Sie wahrscheinlich auf der Suche nach, sequence.
Ørjan Johansen
Ja, das ist wahr. Ich schaue nur auf (<*>)die Unterschrift, die ist m (a → b) → m a → m b. So nah dran ...
totalhuman
1
Es gibt auch Control.Lens.??, die möglicherweise für die Aufnahme in die Basis irgendwann vorgeschlagen wurden.
Ørjan Johansen
Ich möchte die wiederholte extrahieren (.mapM id[fst,snd])wie let r=(.mapM id[fst,snd]) in r(r.zipWith(+)), aber ich habe nicht die typechecker bekommen konnte eine pointfree Version zu übernehmen.
30.
4

54 Bytes

Ich habe ehrlich gesagt Zweifel daran , dass wir @ H.PWiz die 44 Bytes Lösung schlagen wird, aber niemand wurde mit der Tatsache , dass (,)Geräte der Typenklasse Functor, so ist hier eine andere interessant , die nicht so schlecht ist:

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

Probieren Sie es online!

Erläuterung

Die Implementierung der Typklasse Functorfür 2 -Tupel ist der von Either(ab base-4.10.1.0 ) sehr ähnlich :

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ür diese Herausforderung bedeutet dies, dass die folgende Funktion die zweiten Elemente hinzufügt, während das erste Element des zweiten Arguments beibehalten wird:

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

Wenn wir nur einen kleinen Helfer hätten helpPlz = \a b -> (fst a+fst b,snd b), könnten (helpPlz<*>).flip(fmap.(+).snd)und würden wir es tun . Zum Glück haben wir das Werkzeug, pointfreedas uns gibt:

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

Wenn Sie diese Funktion einfach wieder einstecken, gelangen Sie zu der obigen Lösung (beachten Sie, (<*>) = apwelche in der Basis ist ).

ბიმო
quelle
4

60 Bytes

Ich sehe uncurryhier keine Liebe, also dachte ich mir, ich schaue vorbei und repariere das.

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

Ich dachte, mit all dem fstund snd, dass das Auspacken der Argumente mit uncurryeinigen Ergebnissen führen könnte. Offensichtlich war es nicht so fruchtbar, wie ich gehofft hatte.

Silvio Mayolo
quelle
2
uncurryist so wortreich. :( Aber Sie können die äußersten Klammern durch ersetzen $.
Ørjan Johansen
Ja, und das ist leider das Problem mit vielen Funktionsnamen in Haskell. Einfach zu lang zum Golfen. Aber danke für die 1-Zeichen-Ersparnis!
Silvio Mayolo