Tupla aggiunta in inutile


16

Qual è il modo più breve in cui possiamo esprimere la funzione

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

in notazione senza punti?

pointfree.io ci dà

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

che con un po 'di lavoro può essere abbreviato

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

per 76 byte. Ma questo sembra ancora molto lungo e complesso per un compito così semplice. Esiste un modo per esprimere l'aggiunta a coppie come una funzione senza punti più breve?

Per essere chiari con ciò che intendo dire senza punto, una dichiarazione senza punto di una funzione implica prendere funzioni e operatori esistenti e applicarli l'uno all'altro in modo tale da creare la funzione desiderata. Apici inversi, parentesi e valori letterali ( [], 0, [1..3], etc.) sono ammessi, ma parole chiave come whereelet non lo sono. Questo significa:

  • Non è possibile assegnare variabili / funzioni

  • Non puoi usare lambdas

  • Non è possibile importare

Ecco la stessa domanda quando era una CMC


9
Non ho mai capito perché si chiama " senza punti " quando in realtà è pieno di punti. : P
Mr. Xcoder,


5
È un peccato che non ci sia permesso importare il miglior pacchetto Haskell , altrimenti la soluzione sarebbe (+)***(+).
Silvio Mayolo,

2
Un'idea: (+)<$>([1],2)<*>([3],4)([1,3],6).
xnor

2
Ho trascorso un po 'di tempo cercando di creare una soluzione eccellente utilizzando il suggerimento di xnor ... ma ho finito con questa spazzatura . Non so nemmeno perché ci provo a volte ...
totalmente umano il

Risposte:



8

44 byte

-8 byte grazie a Ørjan Johansen. -3 byte grazie a Bruce Forte.

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

Provalo online!

Si traduce in:

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

67 byte

-8 byte grazie a Ørjan Johansen. -1 byte grazie a Bruce Forte.

Se è richiesta l'uscita tupla:

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

Provalo online!

Sì, lo faccio manualmente non producendo frutta matura. Ma sono contento della [a] → (a, a)conversione.

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

Ora se ci fosse una funzione breve con m (a → b) → a → m b.


3
Odio spezzartelo, ma mapM id[fst,snd]è più corto.
Ørjan Johansen,

Purtroppo, mapM idè la golfed versione della funzione probabilmente stai cercando, sequence.
Ørjan Johansen,

Sì è vero. Sto solo guardando (<*>)la firma che è m (a → b) → m a → m b. Così vicino ...
totalmente umano il

1
C'è anche Control.Lens.??, che potrebbe essere stato proposto per l'inclusione nella base ad un certo punto.
Ørjan Johansen,

Voglio estrarre il (.mapM id[fst,snd])like ripetuto let r=(.mapM id[fst,snd]) in r(r.zipWith(+)), ma non sono riuscito a convincere il typechecker ad accettare una versione senza punti.
xnor

4

54 byte

Sinceramente dubito che batteremo la soluzione a 44 byte di @ H.PWiz, ma nessuno stava usando il fatto che (,)implementa la classe type Functor, quindi eccone un'altra interessante che non è poi così male:

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

Provalo online!

Spiegazione

L'implementazione della classe di tipo Functorper 2 -Tuple è molto simile a quella di Either(dalla 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)

Ciò che ciò significa per questa sfida è che la seguente funzione aggiunge i secondi elementi mantenendo il primo elemento del secondo argomento:

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

Quindi, se solo avessimo un piccolo aiuto helpPlz = \a b -> (fst a+fst b,snd b), potremmo fare (helpPlz<*>).flip(fmap.(+).snd)e faremmo. Fortunatamente abbiamo lo strumento pointfreeche ci dà:

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

Quindi semplicemente ricollegando quella funzione arriviamo alla soluzione sopra (nota ciò (<*>) = apche è nella base ).


4

60 byte

Non vedo alcun uncurryamore qui, quindi ho pensato di fare un salto e sistemarlo.

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

Ho pensato, con tutte le fste snd, che scompattare gli argomenti con uncurrypotrebbe produrre alcuni risultati. Chiaramente, non è stato fruttuoso come avevo sperato.


2
uncurryè così prolisso. :( Ma puoi sostituire le parentesi più esterne con $.
Ørjan Johansen,

Sì, e questo è purtroppo il problema con molti nomi di funzioni in Haskell. Troppo a lungo per giocare a golf. Ma grazie per il risparmio di 1 carattere!
Silvio Mayolo,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.