เดี๋ยวก่อนนี่คือภาษาอะไร


37

เมื่อเร็ว ๆ นี้ฉันมีความสุขในการเขียนโปรแกรม Haskell ที่สามารถตรวจจับได้ว่าNegativeLiteralsส่วนขยายนั้นทำงานหรือไม่ ฉันมากับสิ่งต่อไปนี้:

data B=B{u::Integer}
instance Num B where{fromInteger=B;negate _=B 1}
main=print$1==u(-1)

ลองออนไลน์!

สิ่งนี้จะพิมพ์TrueตามปกติและFalseอย่างอื่น

ตอนนี้ฉันสนุกมากที่ได้ทำสิ่งนี้ฉันกำลังขยายความท้าทายให้กับทุกคน ส่วนขยายภาษา Haskell อื่น ๆ ที่คุณสามารถถอดรหัสได้

กฎระเบียบ

จะแตกเป็นส่วนขยายของภาษาโดยเฉพาะอย่างยิ่งคุณต้องเขียนโปรแกรม Haskell ที่รวบรวมทั้งที่มีและไม่มีนามสกุลภาษา (คำเตือนจะมีการปรับ) และผลแตกต่างกันสองไม่ใช่ข้อผิดพลาดค่าทำงานเมื่อมีนามสกุลภาษาและมันปิด (โดยการเพิ่มNoคำนำหน้า ส่วนขยายภาษา) ด้วยวิธีนี้รหัสข้างต้นอาจย่อให้เหลือเพียง:

data B=B{u::Integer}
instance Num B where{fromInteger=B;negate _=B 1}
main=print$u(-1)

ซึ่งพิมพ์1และ-1.

วิธีใดก็ตามที่คุณใช้ในการถอดรหัสส่วนขยายจะต้องเฉพาะกับส่วนขยายนั้น อาจมีวิธีที่จะตรวจจับการตั้งค่าสถานะของคอมไพเลอร์หรือ LanguageExtensions ที่เปิดใช้งานโดยพลการหากวิธีการดังกล่าวไม่ได้รับอนุญาต คุณสามารถเปิดใช้งานส่วนขยายภาษาเพิ่มเติมหรือเปลี่ยนการเพิ่มประสิทธิภาพของคอมไพเลอร์โดย-Oไม่ต้องเสียค่าใช้จ่ายนับไบต์

ส่วนขยายภาษา

คุณไม่สามารถแตกนามสกุลภาษาใด ๆ ที่ไม่ได้มีNoคู่ (เช่นHaskell98, Haskell2010, Unsafe, Trustworthy, Safe) เพราะสิ่งเหล่านี้ไม่ตกอยู่ภายใต้เงื่อนไขที่ระบุไว้ข้างต้น ส่วนขยายภาษาอื่น ๆ เป็นเกมที่ยุติธรรม

เกณฑ์การให้คะแนน

คุณจะได้รับรางวัลหนึ่งคะแนนสำหรับทุกส่วนขยายภาษาที่คุณเป็นคนแรกที่จะถอดรหัสและอีกหนึ่งจุดเพิ่มเติมสำหรับทุก ๆ ส่วนขยายของภาษาที่คุณมีรอยแตกสั้นที่สุด (วัดเป็นไบต์) สำหรับจุดที่สองความสัมพันธ์จะถูกทำลายในความโปรดปรานของการส่งก่อนหน้านี้ คะแนนที่สูงขึ้นจะดีกว่า

คุณจะไม่สามารถทำคะแนนสำหรับการส่งครั้งแรกในNegativeLiteralsหรือQuasiQuotesเพราะฉันได้แตกพวกเขาและรวมไว้ในเนื้อหาของโพสต์ อย่างไรก็ตามคุณจะสามารถทำคะแนนให้กับรอยแตกที่สั้นที่สุดของแต่ละจุดได้ นี่คือรอยแตกของฉันQuasiQuotes

import Text.Heredoc
main=print[here|here<-""] -- |]

ลองออนไลน์!


3
ฉันคิดว่านี่เป็นรายการตัวเลือกที่ใช้ได้ทั้งหมด
H.PWiz

1
โปรดทราบว่าความคิดเห็นข้างต้นของฉันไม่รวมถึงNondecreasingIndentationเหตุผลที่ชัดเจน
H.PWiz

4
ฉันคิดว่าชื่อนี้ทำให้เข้าใจผิดเนื่องจากภาษาเดียวที่คุณสามารถใช้ได้คือ Haskell วิธีการเกี่ยวกับWait, what language extension is this?หรือสิ่งที่แตกต่างอย่างสิ้นเชิง
MD XF

1
ผมค่อนข้างอยากรู้อยากเห็นว่ามันเป็นไปได้ที่จะแตกRelaxedPolyRecสำหรับคอมไพเลอร์พอโบราณจริงสนับสนุนเปิดออก (ตัวเลือกแขวนอยู่กับเอกสารหลายปีหลังจากที่มันหยุดทำอะไร)
dfeuer

1
@dfeuer ดูตั๋วนี้ดูเหมือนว่า GHC 6.12.1 รองรับการปิด
Ørjan Johansen

คำตอบ:


24

MagicHash ขนาด 30 ไบต์

x=1
y#a=2
x#a=1
main=print$x#x

-XMagicHashเอาต์พุต 1, -XNoMagicHashเอาต์พุต 2

MagicHash #ช่วยให้ชื่อตัวแปรที่จะยุติใน ดังนั้นที่มีนามสกุลนี้กำหนดสองฟังก์ชั่นy#และx#แต่ละใช้ค่าและกลับคงที่หรือ2 จะกลับ 1 (เพราะมันใช้กับ)1x#xx#1

โดยไม่มีส่วนขยายนี้กำหนดหนึ่งฟังก์ชั่นซึ่งจะใช้เวลาสองมีปากเสียงและผลตอบแทน# เป็นรูปแบบที่ไม่เคยได้รับมาถึง จากนั้นคือซึ่งจะส่งคืน 22x#a=1x#x1#1


2
ตอนนี้ฉันร้องเพลงX เมจิกแฮปรับแต่งของการเต้นรำเมจิกเต้นรำ ฉันหวังว่าคุณจะภูมิใจ!
TRiG

ฉันประหลาดใจที่MagicHashไม่อนุญาตให้ใช้แฮชที่ไม่ได้ตามมา แปลก!
dfeuer

18

CPP, 33 20 ไบต์

main=print$0-- \
 +1

พิมพ์0ด้วย-XCPPและมี1-XNoCPP

ด้วย-XCPPเครื่องหมายสแลช\ก่อนที่บรรทัดใหม่จะลบบรรทัดใหม่ดังนั้นโค้ดจะกลายเป็นmain=print$0-- +1และ0ถูกพิมพ์เท่านั้นเนื่องจาก+1ตอนนี้เป็นส่วนหนึ่งของความคิดเห็น

ความคิดเห็นจะถูกละเว้นและบรรทัดที่สองจะถูกแยกวิเคราะห์เป็นส่วนหนึ่งของบรรทัดก่อนหน้าเนื่องจากมีการเยื้อง


วิธีก่อนหน้าด้วย #define

x=1{-
#define x 0
-}
main=print x

นอกจากนี้ยังพิมพ์0ด้วย-XCPPและมี1-XNoCPP


2
โอ้พระเจ้าจนกระทั่งบัดนี้ฉันคิดว่า GHC จะตัดความคิดเห็นของ Haskell ก่อนส่งต่อไปยัง CPP
ลูกบาศก์

@Cubic ไม่ใช่โปรเซสเซอร์ล่วงหน้าหรือไม่
Bergi

1
@Bergi แน่นอน แต่ผู้ประมวลผลล่วงหน้าไม่จำเป็นต้องหมายความว่า "เป็นสิ่งแรกที่ทำงาน" โดยเฉพาะอย่างยิ่งเมื่อ GHC ต้องผ่านไฟล์ก่อนเพื่อให้ได้ผลลัพธ์ที่ดี ฉันเดาว่าความคิดเห็นจะถูกเก็บไว้เพื่อให้ความคิดเห็นเอกสารและงานที่คล้ายกันหลังจากทำ CPP
Cubic


14

BinaryLiterals, 57 ไบต์

b1=1
instance Show(a->b)where;show _=""
main=print$(+)0b1

-XBinaryLiteralsพิมพ์บรรทัดใหม่ -XNoBinaryLiterals1พิมพ์

ฉันแน่ใจว่ามีวิธีที่ดีกว่าในการทำเช่นนี้ หากคุณพบโปรดโพสต์มัน


คุณไม่สามารถกำหนดbเป็นฟังก์ชันได้ (ดังนั้นจึงไม่มีเลขฐานสองกลายเป็นb(0, 1)แต่เป็นเลขฐานสอง0b1)?
NoOneIsHere

12

Monomorphism การ จำกัด + อีก 7 คน, 107 ไบต์

สิ่งนี้ใช้ TH ซึ่งต้องการการตั้งค่าสถานะ-XTemplateHaskellตลอดเวลา

ไฟล์ T.hs, 81 + 4 ไบต์

module T where
import Language.Haskell.TH
p=(+)
t=reify(mkName"p")>>=stringE.show

หลัก 22 ไบต์

import T
main=print $t

รวบรวมกับธงMonomorphismRestrictionบังคับประเภทของpการInteger -> Integer -> Integerจึงผลิตออกต่อไปนี้:

"VarI T.p (AppT (AppT ArrowT (ConT GHC.Integer.Type.Integer)) (AppT (AppT ArrowT (ConT GHC.Integer.Type.Integer)) (ConT GHC.Integer.Type.Integer))) Nothing"

การคอมไพล์ด้วยแฟล็ก NoMonomorphismRestrictionจะปล่อยประเภทของค่าpที่ทั่วไปมากที่สุดเช่น Num a => a->a->a- สร้างบางสิ่งเช่น (ย่อVarTชื่อให้a):

"VarI T.p (ForallT [KindedTV a StarT] [AppT (ConT GHC.Num.Num) (VarT a)] (AppT (AppT ArrowT (VarT a)) (AppT (AppT ArrowT (VarT a)) (VarT a)))) Nothing"

ลองออนไลน์!


ทางเลือก

เนื่องจากโค้ดด้านบนพิมพ์เพียงแค่ประเภทของpสิ่งนี้สามารถทำได้กับการตั้งค่าสถานะทั้งหมดที่มีผลต่อวิธี Haskell infers ประเภท ฉันจะระบุเฉพาะค่าสถานะและสิ่งที่จะแทนที่ฟังก์ชันpและหากจำเป็นต้องใช้ค่าสถานะเพิ่มเติม (นอกเหนือจาก-XTemplateHaskell):

OverloadedLists, 106 ไบต์

นอกจากนี้ความต้องการ-XNoMonomorphismRestriction:

p=[]

อย่างใดอย่างหนึ่งp :: [a]หรือp :: IsList l => l, ลองพวกเขาออนไลน์!

OverloadedStrings, 106 ไบต์

นอกจากนี้ความต้องการ-XNoMonomorphismRestriction:

p=""

อย่างใดอย่างหนึ่งp :: Stringหรือp :: IsString s => s, ลองพวกเขาออนไลน์!

PolyKinds 112 ไบต์

ทั้งหมดนี้เกิดจาก @CsongorKiss:

data P a=P 

อย่างใดอย่างหนึ่งP :: P aหรือP :: forall k (a :: k). P a, ลองพวกเขาออนไลน์!

MonadComprehensions, 114 ไบต์

p x=[i|i<-x]

อย่างใดอย่างหนึ่งp :: [a] -> [a]หรือp :: Monad m => m a -> m a, ลองพวกเขาออนไลน์!

NamedWildCards, 114 ไบต์

@Laikoni พบสิ่งนี้สิ่งนี้ต้องการเพิ่มเติม-XPartialTypeSignatures:

p=id::_a->_a

พวกเขาทั้งสองมีประเภทบันทึก ( p :: a -> a) แต่ GHC สร้างชื่อที่แตกต่างกันสำหรับตัวแปรลองใช้ออนไลน์!

ApplicativeDo, 120 ไบต์

p x=do i<-x;pure i

อย่างใดอย่างหนึ่งp :: Monad m => m a -> m aหรือp :: Functor f => f a -> f a, ลองพวกเขาออนไลน์!

OverloadedLabels, 120 ไบต์

สิ่งนี้ต้องการแฟลกเพิ่มเติม-XFlexibleContexts:

p x=(#id)x
(#)=seq

ไม่ว่าจะเป็นประเภทp :: a -> b -> bหรือp :: IsLabel "id" (a->b) => a -> b, ลองพวกเขาออนไลน์!


สิ่งที่คล้ายกันใช้ได้กับธงอื่นหรือไม่
H.PWiz

ใช่คุณสามารถทำมันได้ด้วยOverloadedStringsหรือOverloadedListsเพื่อตรวจสอบและอาจจะคนอื่น ๆ เช่นกัน ..
ბიმო

2
มันใช้ได้กับPolyKinds: ลองออนไลน์!
Csongor จูบ

1
ดูเหมือนว่าจะทำงานกับNamedWildCards: ลองออนไลน์! (ต้องใช้-XPartialTypeSignatures)
Laikoni

10

CPP, 27 25

main=print({-/*-}1{-*/-})

ลองออนไลน์!

พิมพ์()สำหรับ-XCPPและ1สำหรับ-XNoCPP

รุ่นก่อนหน้า:

main=print[1{-/*-},2{-*/-}]

ลองออนไลน์!

พิมพ์[1]ด้วย-XCPPและ[1,2]อื่น ๆ

เครดิต: สิ่งนี้ได้รับแรงบันดาลใจจากคำตอบของ Laikoni แต่แทนที่จะ#defineใช้ความเห็น C เพียงอย่างเดียว


9

ScopedTypeVariables, 162 113 ไบต์

instance Show[()]where show _=""
p::forall a.(Show a,Show[a])=>a->IO()
p a=(print::Show a=>[a]->IO())[a]
main=p()

-XScopedTypeVariablesพิมพ์""(ว่าง) -XNoScopedTypeVariables"[()]"พิมพ์

แก้ไข: โซลูชันที่อัปเดตต้องขอบคุณคำแนะนำที่เป็นประโยชน์ในความคิดเห็น


1
ฉันเข้าใจแล้ว โดยทั่วไปแล้วมันจะดีกว่าที่จะรวมรหัสของคุณไว้ในเนื้อความ ฉันยังสังเกตเห็นว่าสามารถเพียงแค่ถูกแทนที่ด้วย"T" ""
ข้าวสาลีตัวช่วยสร้าง

2
สิ่งที่คุณสามารถทำได้ก็คือแทนที่ประเภทข้อมูลของคุณด้วยT ()เพื่อหลีกเลี่ยงการต้องกำหนด ลองออนไลน์!
ข้าวสาลีตัวช่วยสร้าง

1
เยี่ยมมากฉันเพิ่งรู้ว่า pragma ไม่ต่อเนื่องกันสามารถรวมเป็นธง: ลองออนไลน์!
Csongor จูบ

2
นอกจากนี้show ยังสามารถเปลี่ยนแปลงได้สำหรับการพิมพ์
H.PWiz

ไวยากรณ์ Unicode สำหรับforallจะช่วยให้คุณประหยัดไม่กี่ไบต์ ฉันสงสัยวิธีแก้ปัญหาใด ๆ ที่ต้องการอินสแตนซ์เพิ่มเติมมีความหวังมากในการชนะ
dfeuer

9

MonoLocalBinds, GADTs หรือ TypeFamilies, 36 32 ไบต์

แก้ไข:

  • -4 ไบต์: รุ่นนี้รวมอยู่ในกลุ่มโพลิกล็อตที่ยิ่งใหญ่โดย stasoid ซึ่งทำให้ฉันประหลาดใจด้วยการประกาศทั้งหมดในระดับสูงสุด เห็นได้ชัดว่าก่อให้เกิดข้อ จำกัด นี้ไม่จำเป็นต้องมีการผูกท้องถิ่นที่แท้จริง
a=0
f b=b^a
main=print(f pi,f 0)
  • ด้วยส่วนขยายไม่มี(1.0,1)โปรแกรมนี้พิมพ์
  • มีทั้งของธง-XMonoLocalBinds , -XGADTsหรือ-XTypeFamilies(1.0,1.0)มันพิมพ์

  • มีMonoLocalBindsส่วนขยายเพื่อป้องกันการอนุมานประเภทที่ไม่ใช้งานง่ายซึ่งเรียกโดย GADT และตระกูลประเภท เช่นนี้ส่วนขยายนี้จะเปิดโดยอัตโนมัติอีกสองรายการ

  • มันเป็นไปได้ที่จะปิดอีกครั้งอย่างชัดเจนด้วย-XNoMonoLocalBindsเคล็ดลับนี้จะถือว่าคุณทำไม่ได้
  • เหมือนลูกพี่ลูกน้องที่รู้จักกันดีในการ จำกัด monomorphism MonoLocalBindsทำงานโดยการป้องกันค่าบางอย่าง ( ในการผูกท้องถิ่นเช่นletหรือwhereดังนั้นชื่อที่เห็นได้ชัดว่ามันยังสามารถเกิดขึ้นในระดับบนสุด) จากการ polymorphic แม้จะถูกสร้างขึ้นสำหรับการอนุมานประเภท saner, กฎสำหรับเมื่อมันก่อให้เกิดถ้าเป็นไปได้มีขนดกยิ่งกว่านาย

  • โดยไม่มีนามสกุลใด ๆ ที่อ้างถึงข้างต้นโปรแกรมประเภทf :: Num a => a -> aที่ช่วยให้f piการเริ่มต้นไปDoubleและต่อไปยังf 0Integer

  • ด้วยส่วนขยายประเภทที่อนุมานจะกลายเป็นf :: Double -> Doubleและf 0จะต้องส่งคืนDoubleเช่นกัน
  • ตัวแปรที่แยกจากกันa=0เป็นสิ่งจำเป็นที่จะเรียกกฎระเบียบทางเทคนิค: aโดนข้อ จำกัด monomorphism และaเป็นตัวแปรอิสระของfซึ่งหมายความว่าf's กลุ่มมีผลผูกพันไม่ได้ทั่วไปอย่างเต็มที่ซึ่งหมายความว่าfจะไม่ปิดและทำให้ไม่ได้กลายเป็น polymorphic

9

OverloadedStrings, 65 48 32 ไบต์

การใช้ประโยชน์จาก RebindableSyntax ใช้รุ่นของเราเองของ fromString เพื่อเปิดสตริงใด ๆ "y"ที่เป็นตัวอักษร

main=print""
fromString _=['y']

-XRebindableSyntax -XImplicitPreludeจะต้องรวบรวมกับ

โดยไม่ต้อง-XOverloadedStringsพิมพ์""; "y"ด้วยภาพพิมพ์

ยิ่งไปกว่านั้นมันเพิ่งทำให้ฉันรู้สึกได้ว่าเทคนิคเดียวกันนี้ใช้ได้กับ (เช่น) OverloadedLists:

OverloadedLists, 27 ไบต์

main=print[0]
fromListN=(:)

-XRebindableSyntax -XImplicitPreludeจะต้องรวบรวมกับ

โดยไม่ต้อง-XOverloadedListsพิมพ์[0]; [1,0]ด้วยภาพพิมพ์


1
คุณสามารถย่อบรรทัดสุดท้ายให้fromString a=['y']เป็น
Ørjan Johansen

พื้นที่ในprint "n"สามารถถูกทิ้ง
Laikoni

@ ØrjanJohansenขอบคุณ! ฉันมีมันล้มเหลวด้วย="y"แต่ใช้=['y']งานได้ดี!
felixphew

1
คุณสามารถลบวินาทีnจากprint"n"
Wheat Wizard

1
คุณยังสามารถใช้-XImplicitPreludeหลังจากRebindableSyntaxเพื่อหลีกเลี่ยงการนำเข้าสาย
dfeuer

8

รูปแบบบางส่วน, 32 ไบต์

(!)=seq
main|let f!_=0=print$9!1

-XBangPatternsพิมพ์1ขณะ-XNoBangPatterns0จะพิมพ์

นี้จะทำให้การใช้งานที่ BangPatterns ธงช่วยให้รูปแบบคำอธิบายประกอบกับ!การบังคับให้ประเมินผลเพื่อ WHNF ในกรณีที่จะใช้ความละเอียดระดับบนสุด9!1 (!)=seqหากไม่ได้เปิดใช้งานการตั้งค่าf!_กำหนดผู้ประกอบการใหม่(!)และเงาความหมายระดับบนสุด


7

ApplicativeDo, 104 ไบต์

import Control.Applicative
z=ZipList
instance Monad ZipList where _>>=_=z[]
main=print$do a<-z[1];pure a

ลองออนไลน์!

ด้วยApplicativeDoนี้พิมพ์

ZipList {getZipList = [1]}

ก็ไม่มีมันพิมพ์

ZipList {getZipList = []}

ZipListเป็นหนึ่งในไม่กี่ชนิดในห้องสมุดฐานที่มีอินสแตนซ์สำหรับแต่ไม่ได้สำหรับApplicative Monadอาจมีทางเลือกที่สั้นกว่าแฝงตัวอยู่ที่ไหนสักแห่ง


7

เข้มงวด, 87 84 82 ไบต์

-5 ไบต์ขอบคุณdfeuer !

อาจจะน้อยลงด้วยBlockArgumentsการประหยัด parens รอบ ๆ\_->print 1:

import Control.Exception
0!_=0
main=catch @ErrorCall(print$0!error"")(\_->print 1)

เล่นนี้กับ-XStrictพิมพ์1ในขณะที่ทำงานกับ-XNoStrict0จะพิมพ์ สิ่งนี้ใช้ค่าเริ่มต้นของ Haskell ซึ่งเป็นคนขี้เกียจและไม่จำเป็นต้องประเมินerror""เนื่องจากมันรู้แล้วว่าผลลัพธ์จะเกิดขึ้น0เมื่อจับคู่กับอาร์กิวเมนต์แรกของ(!)พฤติกรรมนี้สามารถเปลี่ยนแปลงได้ด้วยการตั้งค่าสถานะนั้น

หากอนุญาตให้พิมพ์อะไรในกรณีใดกรณีหนึ่งเราสามารถลดขนาดลงเหลือ75 ไบต์เพื่อแทนที่อุปกรณ์หลักด้วย (เช่นบางส่วนถูกปิดโดยdfeuer ):

main=catch @ErrorCall(print$0!error"")mempty

StrictData, 106 99 93 ไบต์

-15 ไบต์ขอบคุณdfeuer !

สิ่งนี้โดยทั่วไปจะทำเหมือนกัน แต่ใช้ได้กับเขตข้อมูลแทน:

import Control.Exception
data D=D()
main=catch @ErrorCall(p$seq(D$error"")0)(\_->p 1);p=print

พิมพ์1ด้วย-XStrictDataธงและ0มี-XNoStrictData

หากอนุญาตให้พิมพ์อะไรในกรณีใดกรณีหนึ่งเราสามารถลดขนาดลงเป็น86 ไบต์โดยแทนที่ส่วนหลักด้วย (19 ไบต์ปิดโดยdfeuer ):

main=catch @ErrorCall(print$seq(D$error"")0)mempty

หมายเหตุ:การแก้ปัญหาทั้งหมดจำเป็นต้องมีการTypeApplicationsตั้งค่า


คุณสามารถลดมันลงได้ค่อนข้างง่ายถึง 98 ไบต์ซึ่งตรงกับโซลูชันของฉัน (แตกต่างกันมาก) TIO
dfeuer

pure()ที่จริงแล้วคุณสามารถทำได้ดียิ่งขึ้นแทนการพิมพ์ในจัดการข้อยกเว้นการใช้เพียง
dfeuer

1
@dfeuer: ดีแล้วD{}เคล็ดลับนั้นค่อนข้างเท่ห์! โกนPartialTypeSignaturesScopedTypeVariables
หนวด

1
@dfeuer: ฉันได้ดูและลองบางสิ่ง แต่ฉันไม่เคยใช้ Generics ดังนั้นฉันอาจไม่ใช่คนที่ใช่
ბიმო

1
คุณสามารถทำได้ดียิ่งขึ้นด้วย GHC ที่มีเลือดออกและ-XBlockArguments:main=catch @ErrorCall(p$seq(D$error"")1)\_->p 3
dfeuer

6

ApplicativeDo, 146 ไบต์

newtype C a=C{u::Int}
instance Functor C where fmap _ _=C 1
instance Applicative C
instance Monad C where _>>=_=C 0
main=print$u$do{_<-C 0;pure 1}

พิมพ์ 1 เมื่อเปิดใช้งาน ApplicativeD 0 มิฉะนั้น

ลองออนไลน์!


1
ขอบคุณ! โอ้ฉันคิดว่าฉันอยู่กับรุ่นเก่าของ GHC ( "ไม่ applicative" ถูกเตือนในระบบของฉัน)
oisdk

3
ใช้ -XDeriveAnyClass คุณสามารถได้รับมาApplicativeและShowเพื่อประหยัดการใช้บันทึกไวยากรณ์เห็นนี้
ბიმო

6

BinaryLiterals, 31 24 ไบต์

แก้ไข:

  • -7 ไบต์: H.PWiz แนะนำให้ปรับเพิ่มเติมโดยใช้b12ตัวแปรเดียว

การปรับเป็นวิธีการของ H.PWizหลีกเลี่ยงอินสแตนซ์ของฟังก์ชัน

b12=1
main=print$(+)0b12

6

ExtendedDefaultRules, 54 53 ไบต์

instance Num()
main=print(toEnum 0::Num a=>Enum a=>a)

พิมพ์()ด้วย-XExtendedDefaultRulesและมี0-XNoExtendedDefaultRules

การตั้งค่าสถานะนี้เปิดใช้งานโดยค่าเริ่มต้นใน GHCi แต่ไม่ใช่ใน GHC ซึ่งเพิ่งสร้างความสับสนให้ฉันแม้ว่าBMOสามารถช่วยเหลือได้อย่างรวดเร็ว

รหัสด้านบนเป็นตัวอย่างรุ่นgolfed ในคู่มือผู้ใช้ GHC ซึ่งอธิบายการเริ่มต้นประเภทใน GHCi

-1 ไบต์ขอบคุณØrjan Johansen !


ขณะที่มองรหัสนี้ยืมพูดได้หลายภาษา (ที่วงเล็บให้ปัญหาบางอย่าง) ผมจำได้ว่า GHC toEnum 0::Num a=>Enum a=>aสนับสนุนหนึ่งไบต์ไวยากรณ์สั้น
Ørjan Johansen

คุณจะได้รับมันลงไป 48 ไบต์ด้วย:PartialTypeSignatures main=print(toEnum 0::_=>Num a=>a)นอกจากนี้ลิงก์ TIO ของคุณล้าสมัย
dfeuer

6

RebindableSyntaxขนาด 25 ไบต์

ฉันอ่านคู่มือที่โพสต์เมื่อเร็ว ๆ นี้ไปยังส่วนขยายของ GHCเมื่อฉันสังเกตเห็นคู่มือง่าย ๆ ที่ฉันยังจำไม่ได้ที่นี่

main|negate<-id=print$ -1

ยังต้องการ-XImplicitPreludeหรืออีกวิธีหนึ่งimport Preludeในรหัสตัวเอง

  • -XRebindableSyntax เปลี่ยนพฤติกรรมของน้ำตาล syntactic ของ Haskell บางส่วนเพื่อให้สามารถกำหนดใหม่ได้
  • -1negate 1เป็นน้ำตาลประโยคสำหรับ
  • ปกตินี้negateเป็นPrelude.negateแต่มีนามสกุลมันเป็น "แล้วแต่จำนวนใดจะnegateอยู่ในขอบเขตที่จุดของการใช้งาน" idซึ่งถูกกำหนดให้เป็น
  • เพราะการขยายความหมายที่จะใช้ในการทำทดแทนสำหรับPreludeโมดูลมันจะปิดการใช้งานนำเข้าโดยปริยายปกติของที่อื่น ๆ แต่Preludeฟังก์ชั่น (ชอบprint) -XImplicitPreludeมีความจำเป็นที่นี่จึงเป็นอีกครั้งที่มีการเปิดใช้งาน

6

เข้มงวด 52 ไบต์

import GHC.IO
f _=print()
main=f$unsafePerformIO$f()

-XStrict

-XNoStrict

ด้วย-XStrict, พิมพ์()เวลาพิเศษ

ขอบคุณ @Sriotchilism O'Zaic เป็นเวลาสองไบต์


6

StrictData, 58 ไบต์

import GHC.Exts
data D=D Int
main=print$unsafeCoerce#D 3+0

(ลิงก์ล้าสมัยเล็กน้อยจะแก้ไข)

-XNoStrictData

-XStrictData

ต้องใช้MagicHash(เพื่อให้เรานำเข้าGHC.ExtsแทนUnsafe.Coerce) และ-O(จำเป็นอย่างยิ่งเพื่อเปิดใช้งานการเปิดใช้ฟิลด์ที่เข้มงวดขนาดเล็ก)

ด้วย-XStrictData, พิมพ์ 3 มิฉะนั้นพิมพ์ค่าจำนวนเต็มของตัวชี้ (อาจถูกแท็ก) ไปยังสำเนาที่จัดสรรไว้ล่วงหน้า3::Integerซึ่งไม่สามารถเป็น 3

คำอธิบาย

มันจะเข้าใจง่ายขึ้นเล็กน้อยด้วยการขยายเล็กน้อยตามประเภทการผิดนัด ด้วยลายเซ็นเราสามารถลดการเพิ่ม

main=print
  (unsafeCoerce# D (3::Integer)
    :: Integer)

ค่าเท่ากัน

main=print
  (unsafeCoerce# $
    D (unsafeCoerce# (3::Integer))
    :: Integer)

ทำไมถึงเคยพิมพ์ 3? ดูเหมือนว่าจะน่าประหลาดใจ! ทีนี้Integerค่าเล็ก ๆจะถูกแทนอย่างมากIntซึ่ง s (ซึ่งมีข้อมูลที่เข้มงวด) จะถูกแทนเหมือนDs เราสิ้นสุดการละเว้นแท็กที่ระบุว่าจำนวนเต็มเล็ก / ใหญ่บวก / ลบ

เหตุใดจึงไม่สามารถพิมพ์ 3 โดยไม่มีนามสกุลได้ การปล่อยให้เหตุผลด้านโครงร่างหน่วยความจำออกมาตัวชี้ข้อมูลที่มีบิตต่ำ (2 ต่ำสุดสำหรับ 32- บิต, 3 ต่ำสุดสำหรับ 64- บิต) ที่ 3 ต้องเป็นตัวแทนของค่าที่สร้างจากตัวสร้างที่สาม ในกรณีนี้ต้องใช้จำนวนเต็มลบ


5

UnboxedTuples ขนาด 52 ไบต์

import Language.Haskell.TH
main=runQ[|(##)|]>>=print

-XTemplateHaskellต้องใช้ พิมพ์ConE GHC.Prim.(##)ด้วย-XUnboxedTuplesและUnboundVarE ##มี-XNoUnboxedTuples


ไม่ควรจะมีอีก 16 คะแนนสำหรับตัวเลือกที่จำเป็น-XTemplateHaskell?
celtschk

2
@celtschk ฉันไม่ได้นับเพราะฉันทามติเมตาปัจจุบันในธงบรรทัดคำสั่งบอกว่าพวกเขาจะไม่ถูกนับ แต่เป็นภาษาใหม่แทน แม้ว่าเมื่อคิดเกี่ยวกับเรื่องนี้ฉันเห็นว่าในบริบทของความท้าทายนี้ซึ่งอนุญาตเฉพาะคำตอบของ Haskell แต่การใช้ธงอื่น ๆ ยังไม่ชัดเจนว่าจะต้องทำอะไร ฉันจะถาม OP เกี่ยวกับเรื่องนี้
Laikoni

ฉันไม่ทราบว่าฉันทามติเกี่ยวกับเรื่องนี้เปลี่ยนไป ขอบคุณสำหรับตัวชี้ การขอ OP เป็นความคิดที่ดีอย่างแน่นอน
celtschk

5

OverloadedLists, 76 ไบต์

import GHC.Exts
instance IsList[()]where fromList=(():)
main=print([]::[()])

ด้วย-XOverloadedLists[()]มันพิมพ์ ด้วย-XNoOverloadedListsจะพิมพ์[]

สิ่งนี้ต้องการธงเพิ่มเติม: -XFlexibleInstances,-XIncoherentInstances


คุณสามารถออกไปกับอินสแตนซ์ที่ทับซ้อนกัน
dfeuer

5

HexFloatLiterals , 49 25 ไบต์

-24 ไบต์ขอบคุณØrjan Johansen

main|(.)<-seq=print$0x0.0

พิมพ์0.0ด้วย-XHexFloatLiteralsและมี0-XNoHexFloatLiterals

ไม่มีลิงก์ TIO เนื่องจากมีการเพิ่ม HexFloatLiterals ใน ghc 8.4.1 แต่ TIO มี ghc 8.2.2


main|(.)<-seq=print$0x0.0หลีกเลี่ยงการซ่อนการนำเข้า
Ørjan Johansen

main|let _._=0=print$0x0.0อาจจะง่ายกว่าสำหรับคนที่พูดได้หลายภาษา
Ørjan Johansen

5

ScopedTypeVariables ขนาด 37 ไบต์

main=print(1::_=>a):: a.a~Float=>_

ยังนี้ต้องUnicodeSyntax, PartialTypeSignatures, และGADTsExplicitForAll

ลองออนไลน์ (ไม่ต้องขยาย)

ลองออนไลน์ (พร้อมส่วนขยาย)

คำอธิบาย

ลายเซ็นประเภทบางส่วนเป็นเพียงการบันทึกไบต์ เราสามารถเติมเต็มได้เช่น:

main=print(1::(Num a, Show a)=>a):: a.a~Float=>IO ()

ด้วยตัวแปรชนิดที่กำหนดขอบเขต, aในประเภทของ1ถูก จำกัด ให้เป็นaในประเภทของmain, ซึ่งตัวเองจะถูก จำกัด ให้เป็นFloat. โดยไม่ต้องตัวแปรประเภทขอบเขต, ค่าเริ่มต้นในการพิมพ์1 Integerเนื่องจากFloatและIntegerค่าจะแสดงแตกต่างกันเราสามารถแยกแยะได้

ขอบคุณ @ ØrjanJohansenสำหรับขนาด 19 ไบต์! เขาตระหนักว่ามันเป็นการดีกว่ามากที่จะใช้ประโยชน์จากความแตกต่างระหว่างShowอินสแตนซ์ของประเภทตัวเลขที่แตกต่างกว่าความแตกต่างในคณิตศาสตร์ของพวกเขา นอกจากนี้เขายังตระหนักว่ามันก็โอเคที่จะออกจากประเภทของmain"syntactically คลุมเครือ" เพราะข้อ จำกัด จริง disambiguates การกำจัดฟังก์ชั่นในท้องถิ่นทำให้ฉันเป็นอิสระด้วยเพื่อลบลายเซ็นประเภทสำหรับmain(เลื่อนไปที่ RHS) เพื่อบันทึกอีกห้าไบต์



@ ØrjanJohansen, ดี
dfeuer

@ ØrjanJohansenฉันควรแก้ไขหรือคุณต้องการเพิ่มของคุณเอง?
dfeuer

แก้ไขมันเป็นวิวัฒนาการที่ค่อยเป็นค่อยไปจากคุณ
Ørjan Johansen

@ ØrjanJohansenขอบคุณที่สวยงาม
dfeuer

5

DeriveAnyClass, 121 113 ไบต์

ขอบคุณdfeuerสำหรับบางไบต์!

import Control.Exception
newtype M=M Int deriving(Show,Num)
main=handle h$print(0::M);h(_::SomeException)=print 1

-XDeriveAnyClassพิมพ์1ขณะ-XNoDeriveAnyClassM 0พิมพ์

นี่คือการใช้ประโยชน์จากข้อเท็จจริงที่ว่า DeriveAnyClass เป็นกลยุทธ์เริ่มต้นเมื่อทั้ง DeriveAnyClass และ GeneralizedNewtypeDeriving เปิดใช้งานตามที่คุณเห็นได้จากคำเตือน ธงนี้อย่างมีความสุขจะสร้างการใช้งานที่ว่างเปล่าสำหรับวิธีการทั้งหมด แต่ GeneralizedNewtypeDeriving เป็นจริงพอสมาร์ทที่จะใช้ดำเนินการประเภทพื้นฐานและตั้งแต่Intเป็นNumมันจะไม่ล้มเหลวในกรณีนี้


หากไม่มีการพิมพ์อะไรในกรณีที่เปิดใช้งานการตั้งค่าสถานะแทนที่mainโดยต่อไปนี้จะเป็น109 ไบต์ :

main=print(0::M)`catch`(mempty::SomeException->_)

อย่างน้อยก็ในrunhaskellเรื่องนี้จริง ๆ แล้วพิมพ์M 1ด้วย-XDeriveAnyClassเนื่องจากความเกียจคร้าน ...
หยุดหัน counterclock ซึ่งเป็น

@ceasedtoturncounterclockwis: ใช่ใน GHCi เช่นกัน แต่เมื่อรวบรวมใน TIO (และเครื่องของฉัน) และจากนั้นทำงานได้ผลใน1:)
ბიმო



1
ฉันลงไปที่ 104 ในวิธีที่แตกต่างอย่างสิ้นเชิงดังนั้นฉันจึงเพิ่มคำตอบของตัวเอง
dfeuer

4

PostfixOperators, 63 ไบต์

import Text.Show.Functions
instance Num(a->b)
main=print(0`id`)

ลองออนไลน์ (ไม่ต้องขยาย)

ลองออนไลน์ (พร้อมส่วนขยาย)

นี้เป็นรุ่นที่ตัดลงของกอด / GHC พูดได้หลายภาษาที่ผมเขียน ดูคำอธิบายที่โพสต์ ขอบคุณ @ ØrjanJohansenที่ทำให้ฉันสามารถใช้idแทนโอเปอเรเตอร์ที่กำหนดเองได้โดยประหยัดสี่ไบต์


id!สามารถนำมาใช้แทน
Ørjan Johansen

@ ØrjanJohansenใช่แน่นอน! นั่นช่วยประหยัดความเย็นสี่ไบต์
dfeuer




3

TemplateHaskell, 140 91 ไบต์

เพิ่งคัดลอกจากmauke ที่มีการปรับเปลี่ยนเล็กน้อย ฉันไม่รู้ว่าเกิดอะไรขึ้น

-49 ไบต์ขอบคุณØrjan Johansen

import Language.Haskell.TH
instance Show(Q a)where show _=""
main=print$(pure$TupE[]::ExpQ)

ลองออนไลน์!


$(...)(ไม่มีช่องว่าง) เป็นแม่แบบไวยากรณ์การประเมินผลเมื่อ TH ถูกเปิดใช้งานและTupE[]( "tuple ว่างเปล่า") ()ให้ การใช้Showอาจทำงานได้ดีสำหรับคนที่พูดได้หลายคน แต่สำหรับความท้าทายนี้ฉันรู้สึกว่าการกำหนดค่าที่จะพิมพ์เป็นสตริงที่ว่างเปล่า ...
Ørjan Johansen

2

MonomorphismRestriction, 31 29 ไบต์

แก้ไข:

  • -2 ไบต์ด้วยการปรับปรุงโดย H.PWiz
f=(2^)
main=print$f$f(6::Int)

-XMonomorphismRestriction0พิมพ์ -XNoMonomorphismRestriction18446744073709551616พิมพ์

  • ด้วยข้อ จำกัด ของทั้งสองใช้fกำลังบังคับให้เป็นชนิดเดียวกันดังนั้นโปรแกรมพิมพ์2^2^6 = 2^64เป็น 64 บิตInt(บนแพลตฟอร์ม 64 บิต) 0ซึ่งจะล้น
  • โดยไม่มีข้อ จำกัด โปรแกรมพิมพ์2^64เป็น Integerbignum

1
ฉันคิดว่าf=(2^);main=print$f$f(64::Int)จะบันทึกไบต์ แต่จะไม่สิ้นสุดตามความเป็นจริง
H.PWiz

@ H.PWiz โชคดี64=2^6ที่ช่วยประหยัดอีกไบต์
Ørjan Johansen

1

ScopedTypeVariables, 119 97 ไบต์

เพิ่งคัดลอกจากmauke ที่มีการปรับเปลี่ยนเล็กน้อย

ขณะนี้มีสองคำตอบอื่น ๆ สำหรับ ScopedTypeVariables: 113 ไบต์โดย Csongor จูบและ 37 ไบต์โดย dfeuer การส่งนี้แตกต่างกันโดยไม่จำเป็นต้องใช้ส่วนขยาย Haskell อื่น ๆ

-22 ไบต์ขอบคุณØrjan Johansen

class(Show a,Num a)=>S a where s::a->IO();s _=print$(id::a->a)0
instance S Float
main=s(0::Float)

ลองออนไลน์!


97 ไบต์ (แม้ว่าIO()/printเคล็ดลับจะไม่ทำงานในกลุ่มภาษา)
Ørjan Johansen

@ ØrjanJohansenฉันเพิ่ม ScopedTypeVariables แต่ยากจน ExtendedDefaultRules สามารถแก้ไขได้อย่างไร? ฉันเคยมีข้อผิดพลาดดังกล่าวมาก่อน แต่ฉันไม่สามารถใช้คำอธิบายของคุณที่นี่ รหัสฉัน ScopedTypeVariables เพิ่มเป็นนี้
Stasoid

ฉันเห็นว่ารหัสใช้เทคนิคการเริ่มต้นที่คล้ายกันและพวกเขาแทรกแซงซึ่งกันและกัน ทางออกหนึ่งคือการปล่อยให้ใหม่ใช้คลาส จำกัด Numมากกว่า ฉันคิดว่าclass(Show a,Floating a)=>K a where{k::a->String;k=pure$ show(f pi)where f=id::a->a};ควรใช้งานได้สะดวกใช้งานFloatและDoubleแสดงผลpiด้วยความแม่นยำที่แตกต่างกัน
Ørjan Johansen

@ ØrjanJohansenว้าวพอดีเลยขอบคุณ
Stasoid
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.