Selain Tuple di pointfree

16

Apa cara terpendek kita dapat mengekspresikan fungsi

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

dalam notasi point-free?

pointfree.io memberi kita

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

yang dengan sedikit kerja bisa disingkat

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

untuk 76 byte. Tapi ini sepertinya masih sangat panjang dan kompleks untuk tugas yang sederhana. Apakah ada cara kami dapat mengekspresikan penambahan berpasangan sebagai fungsi bebas titik yang lebih pendek?

Agar jelas dengan apa yang saya maksud dengan point-free, deklarasi point-free dari suatu fungsi melibatkan pengambilan fungsi dan operator yang ada dan menerapkannya satu sama lain sedemikian rupa sehingga fungsi yang diinginkan dibuat. Backticks, kurung dan nilai-nilai literal ( [], 0, [1..3], dll) diperbolehkan, tetapi kata kunci seperti wheredan lettidak. Ini berarti:

  • Anda tidak boleh menetapkan variabel / fungsi apa pun

  • Anda tidak boleh menggunakan lambdas

  • Anda tidak boleh mengimpor

Inilah pertanyaan yang sama ketika itu adalah CMC

Posting Rock Garf Hunter
sumber
9
Saya tidak pernah mengerti mengapa ini disebut “point- free ” padahal sebenarnya penuh poin. : P
Mr. Xcoder
5
Sayang sekali kami tidak diizinkan mengimpor paket Haskell terbaik , atau solusinya hanya akan (+)***(+).
Silvio Mayolo
2
Sebuah ide: (+)<$>([1],2)<*>([3],4)memberi ([1,3],6).
xnor
2
Saya menghabiskan beberapa waktu mencoba membuat solusi bagus menggunakan tip xnor ... tapi saya berakhir dengan sampah ini . Saya bahkan tidak tahu mengapa saya kadang-kadang mencoba ...
manusiawi

Jawaban:

11

44 byte

Dapat ini dari \x y -> (fst x + fst y, snd x + snd y)

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

Cobalah online!

H.Piz
sumber
8

44 byte

-8 byte berkat Ørjan Johansen. -3 byte terima kasih kepada Bruce Forte.

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

Cobalah online!

Diterjemahkan ke:

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

67 byte

-8 byte berkat Ørjan Johansen. -1 byte terima kasih kepada Bruce Forte.

Jika output tuple diperlukan:

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

Cobalah online!

Yup, saya melakukannya secara manual tidak menghasilkan buah matang. Tapi saya senang dengan [a] → (a, a)pertobatannya.

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

Sekarang jika ada fungsi pendek dengan m (a → b) → a → m b.

benar-benar manusiawi
sumber
3
Benci untuk memberikannya kepada Anda, tetapi mapM id[fst,snd]lebih pendek.
Ørjan Johansen
Sayangnya, mapM idadalah versi golf dari fungsi yang mungkin Anda cari sequence,.
Ørjan Johansen
Ya itu benar. Saya hanya melihat (<*>)tanda tangan yang m (a → b) → m a → m b. Begitu dekat ...
manusiawi
1
Ada juga Control.Lens.??, yang mungkin telah diusulkan untuk dimasukkan dalam basis di beberapa titik.
Ørjan Johansen
Saya ingin mengekstrak (.mapM id[fst,snd])seperti berulang let r=(.mapM id[fst,snd]) in r(r.zipWith(+)), tapi saya belum bisa mendapatkan typechecker untuk menerima versi pointfree.
xnor
4

54 byte

Jujur saya ragu bahwa kita akan mengalahkan solusi 44 byte @ H.PWiz, tetapi tidak ada yang menggunakan fakta yang (,)mengimplementasikan kelas tipe Functor, jadi inilah yang menarik yang tidak terlalu buruk:

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

Cobalah online!

Penjelasan

Implementasi kelas tipe Functoruntuk 2 -Tupel sangat mirip dengan Either(dari basis-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)

Apa artinya ini untuk tantangan ini, adalah bahwa fungsi berikut menambahkan elemen kedua sambil mempertahankan elemen pertama dari argumen kedua:

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

Jadi seandainya kita punya pembantu kecil, helpPlz = \a b -> (fst a+fst b,snd b)kita bisa (helpPlz<*>).flip(fmap.(+).snd)dan akan selesai. Untungnya kami memiliki alat pointfreeyang memberi kami:

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

Jadi dengan hanya memasukkan fungsi itu kembali kita sampai pada solusi di atas (perhatikan apa (<*>) = apyang ada di dasar ).

ბიმო
sumber
4

60 byte

Saya tidak melihat uncurrycinta di sini, jadi saya pikir saya akan muncul dan memperbaikinya.

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

Saya pikir, dengan semua fstdan snd, bahwa membongkar argumen dengan uncurrymungkin menghasilkan beberapa hasil. Jelas, itu tidak berbuah seperti yang saya harapkan.

Silvio Mayolo
sumber
2
uncurrysangat bertele-tele. :( Tetapi Anda dapat mengganti kurung terluar dengan $.
Ørjan Johansen
Ya, dan itu sayangnya masalah dengan banyak nama fungsi di Haskell. Terlalu lama untuk bermain golf. Tapi terima kasih untuk penghematan 1 karakter!
Silvio Mayolo