Baru-baru ini saya merasa senang menulis sebuah program Haskell yang dapat mendeteksi jika NegativeLiterals
ekstensi terlibat. Saya datang dengan yang berikut:
data B=B{u::Integer}
instance Num B where{fromInteger=B;negate _=B 1}
main=print$1==u(-1)
Ini akan mencetak secara True
normal dan False
sebaliknya.
Sekarang aku sangat senang melakukan ini. Aku memperluas tantangan untuk kalian semua. Ekstensi bahasa Haskell apa lagi yang bisa Anda crack?
Aturan
Untuk memecahkan ekstensi bahasa tertentu, Anda harus menulis program Haskell yang mengkompilasi dengan dan tanpa ekstensi bahasa (peringatan baik-baik saja) dan menghasilkan dua nilai non-kesalahan yang berbeda ketika dijalankan dengan ekstensi bahasa dan dimatikan (dengan menambahkan No
awalan ke ekstensi bahasa). Dengan cara ini kode di atas dapat disingkat menjadi hanya:
data B=B{u::Integer}
instance Num B where{fromInteger=B;negate _=B 1}
main=print$u(-1)
yang mencetak 1
dan -1
.
Metode apa pun yang Anda gunakan untuk memecahkan ekstensi harus spesifik untuk ekstensi itu. Mungkin ada cara mendeteksi sewenang-wenang apa bendera compiler atau LanguageExtensions diaktifkan, jika demikian metode tersebut tidak diperbolehkan. Anda dapat mengaktifkan ekstensi bahasa tambahan atau mengubah pengoptimalan kompiler menggunakan -O
tanpa biaya ke jumlah byte Anda.
Ekstensi bahasa
Anda tidak dapat retak ekstensi bahasa yang tidak memiliki No
rekan (misalnya Haskell98
, Haskell2010
, Unsafe
, Trustworthy
, Safe
) karena ini tidak jatuh di bawah ketentuan yang diuraikan di atas. Setiap ekstensi bahasa lainnya adalah permainan yang adil.
Mencetak gol
Anda akan diberikan satu poin untuk setiap ekstensi bahasa Anda adalah orang pertama yang diretas dan satu poin tambahan untuk setiap ekstensi bahasa yang Anda miliki celahnya yang terpendek (diukur dalam byte). Untuk poin kedua, ikatan akan diputus untuk pengajuan sebelumnya. Skor yang lebih tinggi lebih baik
Anda tidak akan dapat mencetak poin untuk pengiriman pertama pada NegativeLiterals
atau QuasiQuotes
karena saya telah memecahkannya dan memasukkannya ke dalam tubuh pos. Namun Anda akan dapat mencetak poin untuk celah terpendek dari masing-masing. Inilah celah sayaQuasiQuotes
import Text.Heredoc
main=print[here|here<-""] -- |]
sumber
NondecreasingIndentation
karena alasan yang jelasWait, what language extension is this?
Atau sesuatu yang sama sekali berbeda.RelaxedPolyRec
, untuk kompiler yang cukup kuno untuk benar - benar mendukung mematikannya. (Pilihan ada di sana, dengan dokumentasi, selama beberapa tahun setelah itu berhenti melakukan apa pun.)Jawaban:
MagicHash, 30 byte
-XMagicHash output 1, -XNoMagicHash output 2
MagicHash memungkinkan nama variabel berakhir di a
#
. Oleh karena itu dengan ekstensi, ini mendefinisikan dua fungsiy#
danx#
yang masing-masing mengambil nilai dan mengembalikan konstanta2
, atau1
.x#x
akan mengembalikan 1 (karenax#
diterapkan ke1
)Tanpa ekstensi, ini mendefinisikan satu fungsi
#
yang mengambil dua argumen dan mengembalikan2
. Itux#a=1
adalah pola yang tidak pernah tercapai. Kemudianx#x
adalah1#1
, yang mengembalikan 2.sumber
MagicHash
tidak memungkinkan hash non-trailing. Aneh!CPP,
3320 byteMencetak
0
dengan-XCPP
dan1
dengan-XNoCPP
.Dengan
-XCPP
, garis miring\
sebelum baris baru menghapus baris baru, sehingga kode menjadimain=print$0-- +1
dan hanya0
dicetak karena+1
sekarang menjadi bagian dari komentar.Tanpa bendera, komentar diabaikan dan baris kedua diuraikan sebagai bagian dari baris sebelumnya karena diindentasi.
Pendekatan sebelumnya dengan
#define
Juga mencetak
0
dengan-XCPP
dan1
dengan-XNoCPP
.sumber
NumDecimals, 14 byte
-XNumDecimals mencetak
10
. -XNoNumDecimals mencetak10.0
.sumber
BinaryLiterals, 57 byte
-XBinaryLiterals mencetak satu baris baru. -XNoBinaryLiterals mencetak a
1
.Saya yakin ada cara yang lebih baik untuk melakukan ini. Jika Anda menemukannya, silakan posting.
sumber
b
sebagai suatu fungsi (jadi tidak ada biner menjadib(0, 1)
, tetapi biner menjadi0b1
)?MonomorphismRestriction + 7 others, 107 byte
Ini menggunakan TH yang membutuhkan bendera
-XTemplateHaskell
setiap saat.File T.hs, 81 + 4 byte
Utama, 22 byte
Mengkompilasi dengan flag MonomorphismRestriction memaksa tipe
p
toInteger -> Integer -> Integer
dan dengan demikian menghasilkan output sebagai berikut:Mengkompilasi dengan flag NoMonomorphismRestriction meninggalkan tipe
p
paling umum, yaitu.Num a => a->a->a
- Memproduksi sesuatu seperti (disingkatVarT
nama menjadia
):Cobalah secara online!
Alternatif
Karena kode di atas hanya mencetak tipe
p
, ini dapat dilakukan dengan semua flag yang entah bagaimana mempengaruhi bagaimana Haskell menyimpulkan tipe. Saya hanya akan menentukan flag dan dengan apa yang akan menggantikan fungsip
dan jika diperlukan flag tambahan (selain itu-XTemplateHaskell
):Daftar Overloaded, 106 byte
Selain itu kebutuhan
-XNoMonomorphismRestriction
:Baik
p :: [a]
ataup :: IsList l => l
, coba online!OverloadedStrings, 106 byte
Selain itu kebutuhan
-XNoMonomorphismRestriction
:Baik
p :: String
ataup :: IsString s => s
, coba online!PolyKinds, 112 byte
Ini sepenuhnya karena @CsongorKiss:
Baik
P :: P a
atauP :: forall k (a :: k). P a
, coba online!Pemahaman Monad, 114 byte
Baik
p :: [a] -> [a]
ataup :: Monad m => m a -> m a
, coba online!NamedWildCards, 114 byte
Yang ini ditemukan oleh @Laikoni, juga membutuhkan
-XPartialTypeSignatures
:Keduanya memiliki tipe save (
p :: a -> a
) tetapi GHC menghasilkan nama yang berbeda untuk variabel, coba online!ApplicativeDo, 120 byte
Baik
p :: Monad m => m a -> m a
ataup :: Functor f => f a -> f a
, coba online!Label Overloaded, 120 byte
Ini perlu bendera tambahan
-XFlexibleContexts
:Baik tipe
p :: a -> b -> b
ataup :: IsLabel "id" (a->b) => a -> b
, coba secara online!sumber
OverloadedStrings
atauOverloadedLists
pasti dan mungkin juga orang lain ..PolyKinds
: Coba online!NamedWildCards
: Coba online! (Membutuhkan-XPartialTypeSignatures
)CPP,
2725Cobalah online!
Cetakan
()
untuk-XCPP
dan1
untuk-XNoCPP
Versi sebelumnya:
Cobalah online!
Mencetak
[1]
dengan-XCPP
dan[1,2]
sebaliknya.Penghargaan: Ini terinspirasi oleh jawaban Laikoni, tetapi alih-alih
#define
hanya menggunakan komentar C.sumber
ScopedTypeVariables,
162113 byteCetakan -XScopedTypeVariables
""
(kosong), -XNoScopedTypeVariables dicetak"[()]"
.Sunting: solusi yang diperbarui berkat saran yang bermanfaat di komentar
sumber
"T"
hanya bisa diganti dengan""
.T
dengan()
. Untuk menghindari harus mendefinisikannya. Cobalah online!show
dapat diubah untuk cetakforall
akan menghemat beberapa byte. Saya ragu solusi apa pun yang membutuhkan contoh tambahan memiliki banyak harapan untuk menang.MonoLocalBinds, GADTs, atau TypeFamilies,
3632 byteEDIT:
(1.0,1)
.Dengan salah satu flag -XMonoLocalBinds , -XGADTs , atau -XTypeFamilies , ia mencetak
(1.0,1.0)
.The
MonoLocalBinds
ekstensi ada untuk mencegah beberapa jenis inferensi unintuitive dipicu oleh GADTs dan keluarga jenis. Dengan demikian, ekstensi ini diaktifkan secara otomatis oleh dua lainnya.-XNoMonoLocalBinds
, trik ini mengasumsikan Anda tidak.Seperti sepupunya yang lebih terkenal, pembatasan monomorfisme,
MonoLocalBinds
bekerja dengan mencegah beberapa nilai (dalam binding lokal sepertiitu juga dapat terjadi pada level atas) dari polimorfik. Meskipun dibuat untuk inferensi tipe yang lebih waras, aturan kapan pemicunya adalah jika mungkin bahkan lebih berbulu dari MR.let
atauwhere
, dengan demikian namaTanpa ekstensi apa pun, program di atas menyimpulkan jenisnya
f :: Num a => a -> a
, memungkinkanf pi
untuk default keDouble
danf 0
keInteger
.f :: Double -> Double
, danf 0
harus mengembalikanDouble
juga.a=0
diperlukan untuk memicu aturan teknis:a
terkena pembatasan monomorphism, dana
merupakan variabel bebas darif
, yang berarti bahwaf
's kelompok yang mengikat tidak sepenuhnya umum , yang berartif
tidak ditutup sehingga tidak menjadi polimorfik.sumber
OverloadedStrings,
654832 byteMengambil keuntungan dari RebindableSyntax, gunakan versi kami sendiri dari Strtring untuk mengubah string literal menjadi
"y"
.Harus dikompilasi dengan
-XRebindableSyntax -XImplicitPrelude
.Tanpa
-XOverloadedStrings
cetakan""
; dengan cetakan"y"
.Juga, baru saja saya sadar bahwa teknik yang sama bekerja dengan (misalnya) Daftar Beban Berlebih:
Daftar Overloaded, 27 byte
Harus dikompilasi dengan
-XRebindableSyntax -XImplicitPrelude
.Tanpa
-XOverloadedLists
cetakan[0]
; dengan cetakan[1,0]
.sumber
fromString a=['y']
.print "n"
juga bisa dijatuhkan.="y"
, tetapi=['y']
berfungsi dengan baik!n
dariprint"n"
-XImplicitPrelude
setelahRebindableSyntax
untuk menghindari jalur impor.BangPatterns, 32 byte
-XBangPatterns mencetak
1
sedangkan -XNoBangPatterns akan mencetak0
.Ini menggunakan bendera BangPatterns yang memungkinkan untuk membubuhi keterangan pola dengan
!
untuk memaksa evaluasi ke WHNF, dalam hal ini9!1
akan menggunakan definisi tingkat atas(!)=seq
. Jika bendera tidak diaktifkan,f!_
tentukan operator baru(!)
dan bayangan definisi tingkat atas.sumber
ApplicativeDo, 104 byte
Cobalah online!
Dengan
ApplicativeDo
, ini tercetakTanpanya, ia mencetak
ZipList
adalah salah satu dari beberapa jenis di pustaka dasar dengan turunan untukApplicative
tetapi tidak untukMonad
. Mungkin ada alternatif yang lebih pendek mengintai di suatu tempat.sumber
Ketat,
87 8482 byte-5 byte berkat dfeuer !
Mungkin kurang dengan
BlockArguments
menyimpan parens di sekitar\_->print 1
:Menjalankan ini dengan -XStrict mencetak
1
sedangkan menjalankannya dengan -XNoStrict akan mencetak a0
. Ini menggunakan bahwa Haskell secara default malas dan tidak perlu mengevaluasierror""
karena sudah tahu bahwa hasilnya akan0
ketika cocok dengan argumen pertama dari(!)
, perilaku ini dapat diubah dengan bendera itu - memaksa runtime untuk mengevaluasi kedua argumen.Jika mencetak apa pun dalam satu kasus diperbolehkan, kami dapat menurunkannya hingga 75 byte menggantikan main by (juga beberapa byte dimatikan oleh dfeuer ):
StrictData,
106 9993 byte-15 byte berkat dfeuer !
Ini pada dasarnya melakukan hal yang sama tetapi bekerja dengan bidang data sebagai gantinya:
Mencetak
1
dengan flag -XStrictData dan0
dengan -XNoStrictData .Jika mencetak apa pun dalam satu wadah diperbolehkan, kami dapat menurunkannya hingga 86 byte menggantikan main by (19 byte off oleh dfeuer ):
Catatan: Semua solusi perlu
TypeApplications
diatur.sumber
pure()
.D{}
triknya keren! Cukur satu lagi dengan menggunakanPartialTypeSignatures
alih-alihScopedTypeVariables
:)-XBlockArguments
:main=catch @ErrorCall(p$seq(D$error"")1)\_->p 3
ApplicativeDo, 146 byte
Mencetak 1 saat ApplicativeDo diaktifkan, 0 sebaliknya
Cobalah online!
sumber
Applicative
danShow
menyimpan menggunakan sintaksis catatan, lihat ini .BinaryLiterals,
3124 byteEdit:
b12
variabel tunggal .Penyesuaian dengan metode H.PWiz , menghindari instance fungsi.
0b12
lexes as0
b12
, mencetak 0 +1 =1
.0b12
lexes as0b1
2
, mencetak 1 + 2 =3
.sumber
ExtendedDefaultRules,
5453 byteMencetak
()
dengan-XExtendedDefaultRules
dan0
dengan-XNoExtendedDefaultRules
.Bendera ini diaktifkan secara default di GHCi, tetapi tidak di GHC, yang baru-baru ini menyebabkan kebingungan bagi saya , meskipun BMO dengan cepat dapat membantu.
Kode di atas adalah versi golf dari contoh di Panduan Pengguna GHC di mana jenis default di GHCi dijelaskan.
-1 byte terima kasih kepada Ørjan Johansen !
sumber
toEnum 0::Num a=>Enum a=>a
.PartialTypeSignatures
:main=print(toEnum 0::_=>Num a=>a)
. Juga, tautan TIO Anda kedaluwarsa.RebindableSyntax , 25 byte
Saya sedang membaca Panduan untuk Ekstensi GHC yang baru-baru ini diposting ketika saya melihat yang mudah yang saya belum ingat melihat di sini.
-1
.1
.Juga membutuhkan
-XImplicitPrelude
, atau sebagai alternatifimport Prelude
dalam kode itu sendiri.-XRebindableSyntax
mengubah perilaku beberapa gula sintaksis Haskell untuk memungkinkannya mendefinisikannya kembali.-1
adalah gula sintaksis untuknegate 1
.negate
adalahPrelude.negate
, tapi dengan ekstensi itu "mananegate
dalam lingkup pada titik penggunaan", yang didefinisikan sebagaiid
.Prelude
modul, ia secara otomatis menonaktifkan impor implisit yang biasa dari itu, tetapiPrelude
fungsi lain (sepertiprint
) diperlukan di sini, jadi itu diaktifkan kembali dengan-XImplicitPrelude
.sumber
Ketat, 52 byte
-Ketat
-XNoStrict
Dengan
-XStrict
, cetakan()
waktu ekstra.Terima kasih kepada @Sriotchilism O'Zaic untuk dua byte.
sumber
StrictData, 58 bytes
(Tautan sedikit ketinggalan zaman; akan diperbaiki.)
-XNoStrictData
-XStrictData
Membutuhkan
MagicHash
(agar kami mengimporGHC.Exts
bukanUnsafe.Coerce
) dan-O
(benar-benar diperlukan, untuk mengaktifkan pembongkaran bidang kecil yang ketat).Dengan
-XStrictData
, mencetak 3. Jika tidak, mencetak nilai integer dari pointer (mungkin ditandai) ke salinan pra-alokasi3::Integer
, yang tidak mungkin 3.Penjelasan
Ini akan menjadi sedikit lebih mudah untuk dipahami dengan sedikit ekspansi, berdasarkan tipe defaulting. Dengan tanda tangan, kita bisa menjatuhkan tambahan.
Setara,
Mengapa cetak 3? Ini sepertinya mengejutkan! Nah,
Integer
nilai-nilai kecil direpresentasikan sangat miripInt
s, yang (dengan data ketat) direpresentasikan seperti ituD
s. Kami akhirnya mengabaikan tag yang menunjukkan apakah bilangan bulat kecil atau besar positif / negatif.Mengapa tidak dapat mencetak 3 tanpa ekstensi? Mengesampingkan alasan tata letak memori, penunjuk data dengan bit rendah (2 terendah untuk 32-bit, 3 terendah untuk 64-bit) dari 3 harus mewakili nilai yang dibangun dari konstruktor ketiga. Dalam hal ini, itu akan membutuhkan bilangan bulat negatif .
sumber
UnboxedTuples, 52 byte
Membutuhkan
-XTemplateHaskell
. MencetakConE GHC.Prim.(##)
dengan -XUnboxedTuples danUnboundVarE ##
dengan -XNoUnboxedTuples .sumber
-XTemplateHaskell
?Daftar Overloaded, 76 byte
Dengan -XOverloadedLists mencetak
[()]
. Dengan -XNoOverloadedLists mencetak[]
Ini membutuhkan bendera tambahan:
-XFlexibleInstances
,-XIncoherentInstances
sumber
HexFloatLiterals ,
4925 byte-24 byte berkat Ørjan Johansen.
Mencetak
0.0
dengan-XHexFloatLiterals
dan0
dengan-XNoHexFloatLiterals
.Tidak ada tautan TIO karena HexFloatLiterals ditambahkan dalam ghc 8.4.1, tetapi TIO memiliki ghc 8.2.2.
sumber
main|(.)<-seq=print$0x0.0
menghindari persembunyian impor.main|let _._=0=print$0x0.0
mungkin lebih mudah untuk polyglot.ScopedTypeVariables, 37 byte
Ini juga memerlukan
UnicodeSyntax
,PartialTypeSignatures
,GADTs
, danExplicitForAll
.Cobalah online (tanpa ekstensi)
Cobalah online (dengan ekstensi)
Penjelasan
Jenis tanda tangan parsial hanya untuk menyimpan byte. Kita bisa mengisinya seperti ini:
Dengan variabel tipe cakupan,
a
dalam tipe1
dibatasi menjadia
tipemain
, yang dengan sendirinya dibatasiFloat
. Tanpa variabel tipe cakupan,1
default untuk mengetikInteger
. SejakFloat
danInteger
nilai ditampilkan secara berbeda, kita dapat membedakannya.Terima kasih kepada @ ØrjanJohansen untuk 19 byte kekalahan! Dia menyadari bahwa itu jauh lebih baik untuk mengambil keuntungan dari perbedaan antara
Show
contoh dari tipe numerik yang berbeda daripada perbedaan dalam hitungnya. Dia juga menyadari bahwa tidak apa-apa untuk meninggalkan jenismain
"ambigu secara sintaksis" karena kendala sebenarnya merusaknya. Menyingkirkan fungsi lokal juga membebaskan saya untuk menghapus tanda tangan tipe untukmain
(menggesernya ke RHS) untuk menghemat lima byte lagi.sumber
DeriveAnyClass,
121113 byteBerkat dfeuer untuk beberapa byte!
-XDeriveAnyClass mencetak
1
sedangkan -XNoDeriveAnyClass mencetakM 0
.Ini mengeksploitasi fakta bahwa DeriveAnyClass adalah strategi default ketika DeriveAnyClass dan GeneralizedNewtypeDeriving diaktifkan, seperti yang dapat Anda lihat dari peringatan. Bendera ini akan dengan senang hati menghasilkan implementasi kosong untuk semua metode, tetapi GeneralizedNewtypeDeriving sebenarnya cukup pintar untuk menggunakan implementasi tipe yang mendasarinya dan karena
Int
merupakanNum
tidak akan gagal dalam hal ini.Jika tidak mencetak apa-apa jika bendera diaktifkan menggantikan
main
yang berikut ini akan menjadi 109 byte :sumber
runhaskell
, ini benar-benar dicetakM 1
dengan-XDeriveAnyClass
, karena kemalasan ...1
:)PostfixOperators, 63 byte
Cobalah online (tanpa ekstensi)
Cobalah online (dengan ekstensi)
Ini adalah versi cut-down polyglot Hugs / GHC yang saya tulis . Lihat posting itu untuk penjelasan. Terima kasih kepada @ ØrjanJohansen karena menyadari bahwa saya dapat menggunakan
id
alih-alih operator kustom, menghemat empat byte.sumber
id
bisa digunakan sebagai ganti!
.DeriveAnyClass, 104 byte
Cobalah online (tanpa ekstensi)
Cobalah online (dengan ekstensi)
Juga membutuhkan
GeneralizedNewtypeDeriving
.sumber
StrictData, 97 byte
Cobalah online (tidak ada data ketat)
Cobalah online (data ketat)
Juga membutuhkan
DeriveGeneric
.sumber
UnicodeSyntax, 33 byte
Cobalah online!
sumber
TemplateHaskell,
14091 byteBaru saja disalin dari mauke dengan modifikasi kecil. Saya tidak tahu apa yang sedang terjadi.
-49 byte berkat Ørjan Johansen.
Cobalah online!
sumber
$(...)
(tanpa spasi) adalah sintaks evaluasi templat ketika TH diaktifkan, danTupE[]
("tuple kosong") memberikan()
. MenggunakanShow
mungkin bekerja dengan baik untuk polyglot, meskipun untuk tantangan khusus ini saya merasa agak buruk tentang mendefinisikan nilai untuk dicetak sebagai string kosong ...Pembatasan Monomorfisme,
3129 byteEdit:
-XMonomorphismRestriction mencetak
0
. -XNoMonomorphismRestriction mencetak18446744073709551616
.f
dipaksa untuk menjadi tipe yang sama, sehingga program mencetak2^2^6 = 2^64
sebagai 64-bitInt
(pada platform 64-bit), yang meluap ke0
.2^64
sebagai bignumInteger
.sumber
f=(2^);main=print$f$f(64::Int)
akan menghemat satu byte. Tapi itu tidak akan berakhir secara realistis64=2^6
, yang menyimpan byte lain.ScopedTypeVariables,
11997 byteBaru saja disalin dari mauke dengan modifikasi kecil.
Saat ini ada dua jawaban lain untuk ScopedTypeVariables: 113 byte oleh Csongor Kiss dan 37 byte oleh dfeuer . Kiriman ini berbeda karena tidak memerlukan ekstensi Haskell lainnya.
-22 byte berkat Ørjan Johansen.
Cobalah online!
sumber
IO()/print
triknya tidak akan bekerja di polyglot).Num
. Saya pikirclass(Show a,Floating a)=>K a where{k::a->String;k=pure$ show(f pi)where f=id::a->a};
harus bekerja, mudah menggunakannyaFloat
danDouble
tampilanpi
dengan presisi berbeda.