Melihat melalui Haskell Prelude, saya melihat sebuah fungsi const
:
const x _ = x
Sepertinya saya tidak dapat menemukan sesuatu yang relevan tentang fungsi ini.
Apa gunanya? Adakah yang bisa memberi contoh di mana fungsi ini dapat digunakan?
Melihat melalui Haskell Prelude, saya melihat sebuah fungsi const
:
const x _ = x
Sepertinya saya tidak dapat menemukan sesuatu yang relevan tentang fungsi ini.
Apa gunanya? Adakah yang bisa memberi contoh di mana fungsi ini dapat digunakan?
backgroundColor :: Text -> Color
untuk sayabackgroundColor = const White
Jawaban:
Ini berguna untuk meneruskan ke fungsi tingkat tinggi saat Anda tidak membutuhkan semua fleksibilitasnya. Misalnya, operator urutan monadik
>>
dapat didefinisikan dalam istilah operator ikatan monad sebagaix >> y = x >>= const y
Ini agak lebih rapi daripada menggunakan lambda
x >> y = x >>= \_ -> y
dan Anda bahkan dapat menggunakannya tanpa poin
meskipun saya tidak terlalu merekomendasikan itu dalam kasus ini.
sumber
map (const 42) [1..5]
hasilnya[42, 42, 42, 42, 42]
.const
berguna untuk menerapkan argumen tunggal untuk menghasilkan fungsi yang dibutuhkan (seperti meneruskan kemap
).head = foldr const (error "Prelude.head: empty list")
Untuk menambah jawaban langsung hammar yang sangat baik: fungsi sederhana seperti
const
danid
sangat berguna sebagai fungsi orde tinggi untuk alasan yang sama bahwa mereka fundamental dalam kalkulus kombinator SKI .Bukannya saya pikir fungsi pendahuluan haskell dimodelkan secara sadar setelah sistem formal atau apa pun. Hanya saja membuat abstraksi yang kaya di haskell sangat mudah, jadi Anda sering melihat jenis hal teoretis ini muncul sebagai berguna secara praktis.
Steker tak tahu malu, tapi saya membuat blog tentang bagaimana contoh Aplikatif
(->)
sebenarnya adalahS
danK
kombinator di sini , jika itu jenis yang Anda sukai.sumber
((->) e)
juga pembaca monad - denganReader
dan sejenisnya hanya menjadinewtype
pembungkus - danask
fungsinya kemudianid
, jadi ituI
kombinatornya juga. Jika Anda melihat sebaliknya di dasar BCKW asli Haskell Curry,B
,K
, danW
adalahfmap
,return
, danjoin
masing-masing.Contoh sederhana untuk digunakan
const
adalahData.Functor.(<$)
. Dengan fungsi ini Anda dapat mengatakan: Saya memiliki sebuah functor dengan sesuatu yang membosankan di dalamnya, tetapi sebaliknya saya ingin memiliki hal menarik lainnya di dalamnya, tanpa mengubah bentuk dari functor. Misalnyaimport Data.Functor 42 <$ Just "boring" --> Just 42 42 <$ Nothing --> Nothing "cool" <$ ["nonsense","stupid","uninteresting"] --> ["cool","cool","cool"]
Definisinya adalah:
atau ditulis tidak sia-sia:
cool <$ uncool = fmap (const cool) uncool
Anda melihat bagaimana
const
digunakan di sini untuk "melupakan" tentang input.sumber
Banyak dari jawaban lain membahas aplikasi yang relatif esoteris (setidaknya bagi pendatang baru)
const
. Ini yang sederhana: Anda bisa menggunakanconst
lambda yang membutuhkan dua argumen, membuang yang pertama tetapi melakukan sesuatu yang menarik dengan yang kedua.Misalnya, implementasi (tidak efisien tetapi instruktif) berikut ini
length
,length' = foldr (\_ acc -> 1 + acc) 0
dapat ditulis ulang sebagai
length' = foldr (const (1+)) 0
yang mungkin lebih elegan.
Ekspresi
const (1+)
memang secara semantik setara dengan\_ acc -> 1 + acc
, karena mengambil satu argumen, membuangnya, dan mengembalikan bagian tersebut(1+)
.sumber
Penggunaan lain adalah untuk mengimplementasikan fungsi anggota kelas yang memiliki argumen dummy yang tidak boleh dievaluasi (digunakan untuk menyelesaikan tipe yang ambigu). Contoh yang mungkin ada di Data.bits:
instance Bits Int where isSigned = const True bitSize = const wordSize ...
Dengan menggunakan const, kami secara eksplisit mengatakan bahwa kami mendefinisikan nilai konstan.
Secara pribadi saya tidak suka penggunaan parameter dummy, tetapi jika mereka digunakan di kelas maka ini adalah cara yang bagus untuk menulis instance.
sumber
const
mungkin hanya implementasi yang Anda cari dalam hubungannya dengan fungsi lain. Inilah contoh yang saya temukan.Katakanlah kita ingin menulis ulang struktur 2-tupel menjadi struktur 2-tupel lainnya. Saya mungkin mengungkapkan ini sebagai:
((a,b),(c,d)) ⇒ (a,(c,(5,a)))
Saya dapat memberikan definisi langsung dengan pencocokan pola:
f ((a,b),(c,d)) = (a,(c,(5,a)))
Bagaimana jika saya menginginkan solusi yang tidak berguna (diam-diam) untuk penulisan ulang semacam ini? Beberapa berpikir dan mengotak-atik nanti, jawabannya adalah kita dapat mengekspresikan penulisan ulang apa pun
(&&&), const, (.), fst, snd
. Perhatikan itu(&&&)
dariControl.Arrow
.Solusi dari contoh yang menggunakan fungsi ini adalah:
(fst.fst &&& (fst.snd &&& (const 5 &&& fst.fst)))
Perhatikan kesamaannya dengan
(a,(c,(5,a)))
. Bagaimana jika kita ganti&&&
dengan,
? Kemudian berbunyi:(fst.fst, (fst.snd, (const 5, fst.fst)))
Perhatikan bagaimana
a
elemen pertama dari elemen pertama, dan itulahfst.fst
proyek. Perhatikan bagaimanac
elemen pertama dari elemen kedua, dan itulahfst.snd
proyek. Artinya, variabel menjadi jalur ke sumbernya.const
memungkinkan kami untuk memperkenalkan konstanta. Menarik bagaimana nama itu sejajar dengan artinya!Saya kemudian digeneralisasi ide ini dengan Aplikatif sehingga Anda dapat menulis fungsi apapun dalam gaya sia-sia (asalkan Anda memiliki analisis kasus tersedia sebagai fungsi, seperti
maybe
,either
,bool
). Sekali lagi,const
memainkan peran memperkenalkan konstanta. Anda dapat melihat pekerjaan ini di paket Data.Function.Tacit .Ketika Anda memulai secara abstrak, pada tujuan, dan kemudian bekerja menuju implementasi, Anda akan terkejut dengan jawabannya. Artinya, salah satu fungsi mungkin sama misteriusnya dengan salah satu roda penggerak dalam mesin. Namun, jika Anda mundur untuk menampilkan seluruh mesin, Anda dapat memahami konteks di mana roda gigi itu diperlukan.
sumber
Katakanlah Anda ingin membuat daftar yang
Nothings
sama dengan panjang string. Saatconst
mengembalikan argumen pertamanya, tidak peduli argumen kedua, Anda dapat melakukan:listOfNothings :: String -> [Maybe Char] listOfNothings = (map . const) Nothing
atau, lebih jelasnya:
listOfNothing st = map (const Nothing) st
sumber
Katakanlah Anda ingin memutar daftar. Ini adalah cara idiomatik untuk melakukannya di Haskell:
rotate :: Int -> [a] -> [a] rotate _ [] = [] rotate n xs = zipWith const (drop n (cycle xs)) xs
Fungsi ini menggabungkan dua larik dengan fungsi tersebut
const
, yang pertama adalah larik siklik tak hingga, yang kedua adalah larik yang Anda gunakan untuk memulai.const
bertindak sebagai pemeriksaan batas, dan menggunakan larik asli untuk menghentikan larik siklik.Lihat: Memutar daftar di Haskell
sumber
Misalkan Anda ingin membuat semua urutan dari daftar yang diberikan.
Untuk setiap elemen daftar, pada titik tertentu Anda memiliki pilihan Benar (sertakan dalam urutan saat ini) atau Salah (jangan sertakan). Ini dapat dilakukan dengan menggunakan fungsi filterM .
Seperti ini:
λ> import Control.Monad λ> :t filterM filterM :: Applicative m => (a -> m Bool) -> [a] -> m [a] λ>
Misalnya, kami menginginkan semua urutan
[1..4]
.λ> filterM (const [True, False]) [1..4] [[1,2,3,4],[1,2,3],[1,2,4],[1,2],[1,3,4],[1,3],[1,4],[1],[2,3,4],[2,3],[2,4],[2],[3,4],[3],[4],[]] λ>
sumber