Fungsi a -> b -> (a -> b) terpendek di Haskell

19

Saya mendapat pertanyaan berikut saat ujian:

Tulis fungsi fdengan tipe berikut a -> b -> (a -> b). adan bseharusnya tidak terikat dalam arti apa pun, semakin pendek kode, semakin baik.

Saya datang dengan f a b = \x -> snd ([a,x],b). Bisakah Anda menemukan sesuatu yang lebih kecil?

Saat ini pemenangnya adalah: f _=(.f).const

Radu Stoenescu
sumber
Jika jenis yang lebih umum diperbolehkan: f = const const.
hammar
@hammar: atau f _ b _ = b, tetapi, mengingat solusi dalam pertanyaan, saya curiga jenis yang lebih umum tidak diperbolehkan.
Tikhon Jelvis
6
Jika jenis yang lebih umum diperbolehkan, mengapa tidak f = id?
Tom Ellis
7
Sebenarnya jika jenis yang lebih umum diperbolehkan maka itu f = fadalah solusi, jadi saya kira kondisi pada jenis itu sangat penting!
Tom Ellis
2
Jenis yang lebih umum tidak diperbolehkan, asumsi Anda benar.
Radu Stoenescu

Jawaban:

11

Contoh Anda dapat menyusut dengan menyingkirkan fungsi anonim di sebelah kanan:

f a b x = snd ([a,x],b)

Ini berfungsi karena jenisnya a -> b -> a -> bsetara dengan a -> b -> (a -> b)di Haskell.

Matt Fenwick
sumber
4
Modifikasi sedikit lebih pendek:f a b x = snd (f x,b)
Ed'ka
5

Fungsi f _=(.f).constsebenarnya dari jenis yang lebih umum daripada f :: a -> b -> (a -> b), yaitu f :: a -> b -> (c -> b). Jika tidak ada tanda tangan tipe yang diberikan, sistem inferensi tipe menyimpulkan tipe f :: a -> b -> (a -> b), tetapi jika Anda menyertakan tanda tangan tipe f :: a -> b -> (c -> b)dengan definisi yang sama persis, Haskell akan mengkompilasinya tanpa masalah dan akan melaporkan tipe yang konsisten untuk aplikasi parsial dari f. Mungkin ada beberapa alasan mendalam mengapa sistem inferensi tipe lebih ketat daripada sistem pengecekan tipe dalam kasus ini, tetapi saya tidak cukup memahami teori kategori untuk muncul dengan alasan mengapa ini harus terjadi. Jika Anda tidak yakin, Anda dapat mencobanya sendiri.

archaephyrryx
sumber
mungkin seperti kasus f a b = f a a. itu menyimpulkan menjadi tipe a -> a -> bmeskipun sesuai dengan tipe a -> b -> c. itu karena jika ftidak diberikan suatu tipe, ia hanya dapat menggunakan dirinya secara monomorfis.
haskeller bangga
Saya tidak berpikir ini akan jadi masalah
haskeller bangga
4

Mengingat ScopedTypeVariables, saya datang dengan ini:

f (_::a) b (_::a) = b

Jika Anda menyusutkan fungsi saya dan milik Anda, rambut saya lebih pendek:

f(_::a)b(_::a)=b
f a b x=snd([a,x],b)

Tentu saja, Anda mungkin tidak diizinkan untuk mengandalkan ScopedTypeVariables: P.

Tikhon Jelvis
sumber
3
Ini tidak sesingkat f _=(.f).const( karena Sassa NF ). Yang juga tidak perlu ScopedTypeVariables.
Berhenti menghidupkan counterclockwis
Hmm, awalnya saya pikir ini akan memerlukan argumen pertama dan ketiga untuk menjadi daftar ...
Chris Taylor
@ChrisTaylor: Terlalu banyak OCaml dalam pikiran? :)
Tikhon Jelvis
Hah, pasti! ;)
Chris Taylor