เลขคณิตตีความ


9

ข้อเท็จจริงที่รู้จักกันเล็กน้อยคือถ้าคุณเปิดส่วนขยายภาษามากพอ (ghc) Haskell จะกลายเป็นภาษาที่แปลแบบไดนามิก! ตัวอย่างเช่นโปรแกรมต่อไปนี้ใช้การเพิ่ม

{-# Language MultiParamTypeClasses, FunctionalDependencies, FlexibleInstances, UndecidableInstances #-}

data Zero
data Succ a

class Add a b c | a b -> c
instance Add Zero a a
instance (Add a b c) => Add (Succ a) b (Succ c)

มันไม่ได้ดูเหมือน Haskell อีกต่อไป สำหรับหนึ่งแทนที่จะใช้งานมากกว่าวัตถุเราดำเนินงานมากกว่าประเภท แต่ละหมายเลขเป็นประเภทของตัวเอง แทนที่จะเป็นฟังก์ชั่นเรามีคลาสประเภท ฟังก์ชันการพึ่งพาช่วยให้เราสามารถใช้พวกเขาเป็นฟังก์ชั่นระหว่างประเภท

ดังนั้นเราจะเรียกรหัสของเราได้อย่างไร เราใช้คลาสอื่น

class Test a | -> a
 where test :: a
instance (Add (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)
  => Test a

นี่เป็นการกำหนดประเภทของtestประเภท 4 + 3 หากเราเปิดสิ่งนี้ขึ้นใน ghci เราจะพบว่าtestเป็นประเภทที่ 7:

Ok, one module loaded.
*Main> :t test
test :: Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero))))))

งาน

ฉันต้องการให้คุณใช้คลาสที่คูณ Peano สองตัว (จำนวนเต็มไม่เป็นลบ) ตัวเลข Peano จะถูกสร้างขึ้นโดยใช้ชนิดข้อมูลเดียวกันในตัวอย่างด้านบน:

data Zero
data Succ a

และชั้นเรียนของคุณจะได้รับการประเมินในลักษณะเดียวกันกับข้างบนเช่นกัน คุณสามารถตั้งชื่อชั้นเรียนของคุณตามที่คุณต้องการ

คุณสามารถใช้ส่วนขยายภาษา ghc ใด ๆ ที่คุณต้องการโดยไม่มีค่าใช้จ่ายเป็นไบต์

กรณีทดสอบ

กรณีทดสอบเหล่านี้สมมติว่าคลาสของคุณมีชื่อMคุณสามารถตั้งชื่ออย่างอื่นได้หากต้องการ

class Test1 a| ->a where test1::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ (Succ (Succ Zero))) a)=>Test1 a

class Test2 a| ->a where test2::a
instance (M Zero (Succ (Succ Zero)) a)=>Test2 a

class Test3 a| ->a where test3::a
instance (M (Succ (Succ (Succ (Succ Zero)))) (Succ Zero) a)=>Test3 a

class Test4 a| ->a where test4::a
instance (M (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))) (Succ (Succ (Succ Zero))) a)=>Test4 a

ผล

*Main> :t test1
test1
  :: Succ
       (Succ
          (Succ
             (Succ
                (Succ (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))
*Main> :t test2
test2 :: Zero
*Main> :t test3
test3 :: Succ (Succ (Succ (Succ Zero)))
*Main> :t test4
test4
  :: Succ
       (Succ
          (Succ
             (Succ
                (Succ
                   (Succ
                      (Succ
                         (Succ
                            (Succ
                               (Succ
                                  (Succ
                                     (Succ (Succ (Succ (Succ (Succ (Succ (Succ Zero)))))))))))))))))

ดึงแรงบันดาลใจจากTyping การสัมภาษณ์ทางเทคนิค


ส่วนขยายภาษาฟรีหรือไม่ ถ้าเป็นเช่นนั้น
Potato44

@ Potato44 โอ้ใช่แล้ว ส่วนขยายภาษาทั้งหมดฟรี
Ad Hoc Garf Hunter

1
เฮ้ ... ดูเหมือนโพสต์นี้ meme-y แม้ว่าจะไม่ใช่
Magic Octopus Urn

คำตอบ:


9

130 121 ไบต์

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

type family a+b where s a+b=a+s b;z+b=b
type family a*b where s a*b=a*b+b;z*b=z
class(a#b)c|a b->c
instance a*b~c=>(a#b)c

ลองออนไลน์!

ครอบครัวนี้กำหนดประเภทปิดสำหรับการเพิ่มและการคูณ(+) (*)จากนั้นคลาสคลาส(#)จะถูกกำหนดที่ใช้(*)ตระกูลตระกูลพร้อมกับข้อ จำกัด ด้านความเท่าเทียมกันในการแปลงจากโลกประเภทแฟมิลีสู่โลกของอารัมภบทประเภท


3
หากคุณสลับสมการคุณสามารถแทนที่โดยZero z
Ørjan Johansen

1
@ ØrjanJohansenเรียบร้อยแล้ว ฉันบันทึก 9 ไบต์สำหรับใครบางคนและบันทึก 9 ไบต์สำหรับฉัน
Potato44

ฉันไม่รู้ว่าจะใช้ตระกูลตระกูลแบบไหน แต่ฟังก์ชั่นแบบนี้คุณจึงไม่จำเป็นต้องกำหนดว่า+มีประโยชน์หรือไม่?
ลินน์

@ ลินน์ที่จบออกมาอีกต่อไป TIO
Potato44

1
@WeatWizard ฉันเพิ่งรู้ว่ารหัสที่ฉันโพสต์ในความคิดเห็นเพราะมันออกมาอีกต่อไปเป็นหลักรุ่นหางคำตอบของคุณซ้ำ
Potato44

6

139 ไบต์

class(a+b)c|a b->c;instance(Zero+a)a;instance(a+b)c=>(s a+b)(s c)
class(a*b)c|a b->c;instance(Zero*a)Zero;instance((a*b)c,(b+c)d)=>(s a*b)d

ลองออนไลน์!

*กำหนดผู้ประกอบการประเภท เทียบเท่ากับโปรแกรม Prolog:

plus(0, A, A).
plus(s(A), B, s(C)) :- plus(A, B, C).
mult(0, _, 0).
mult(s(A), B, D) :- mult(A, B, C), plus(B, C, D).

Potato44 และ Hat Wizard บันทึกแต่ละ 9 ไบต์ ขอบคุณ!


คุณไม่จำเป็นต้องนับการประกาศข้อมูลของคุณเป็นจำนวนไบต์ทั้งหมด ฉันจะทำให้คำถามนี้ชัดเจนขึ้นเมื่อฉันได้รับโอกาส
Ad Hoc Garf Hunter

นอกจากนี้ผมคิดว่าคุณสามารถใช้ทั่วไปแทนf Succ
Ad Hoc Garf Hunter

1
คุณสามารถบันทึก 9 ไบต์โดยการโคลอนโคลอน
Potato44

ฉันคิดว่าตัวช่วยสร้างหมวกช่วยชีวิตด้วย 9 ไม่ใช่ 6 มีเหตุการณ์เกิดขึ้นสามครั้งใน Succ
Potato44

1

รุ่นครอบครัว 115 ไบต์

type family(a%b)c where(a%b)(s c)=s((a%b)c);(s a%b)z=(a%b)b;(z%b)z=z
class(a#b)c|a b->c
instance(a%b)Zero~c=>(a#b)c

ลองออนไลน์!

นี่คือความหมายของครอบครัวปิดประเภทเช่นpotato44 ของ ยกเว้นซึ่งแตกต่างจากคำตอบอื่น ๆ ฉันใช้ตระกูลประเภทเดียวเท่านั้น

type family(a%b)c where
  -- If the accumulator is Succ c:
  -- the answer is Succ of the answer if the accumulator were c
  (a%b)(s c)=s((a%b)c)
  -- If the left hand argument is Succ a, and the right hand is b
  -- the result is the result if the left were a and the accumulator were b
  (s a%b)z=(a%b)b
  -- If the left hand argument is zero
  -- the result is zero
  (z%b)z=z

สิ่งนี้กำหนดโอเปอเรเตอร์สามประเภท (a*b)+cมันเป็นหลักดำเนินการ เมื่อใดก็ตามที่เราต้องการเพิ่มอาร์กิวเมนต์มือขวาของเราไปยังผลรวมเราจะใส่มันเข้าไปในตัวสะสม

สิ่งนี้ทำให้เราไม่จำเป็นต้องกำหนด(+)เลย ในทางเทคนิคคุณสามารถใช้ตระกูลนี้เพื่อดำเนินการเพิ่มเติมได้

class Add a b c | a b -> c
instance (Succ Zero % a) b ~ c => Add a b c

รุ่นคลาส 137 ไบต์

class(a#b)c d|a b c->d
instance(a#b)c d=>(a#b)(f c)(f d)
instance(a#b)b d=>(f a#b)Zero d
instance(Zero#a)Zero Zero
type(a*b)c=(a#b)Zero c

ลองออนไลน์!

รุ่นคลาสนี้จะสูญเสียรุ่นพื้นฐานไปบางส่วน แต่ก็ยังสั้นกว่ารุ่นคลาสที่สั้นที่สุดที่นี่ มันใช้วิธีการเดียวกันกับเวอร์ชั่นครอบครัวของฉัน


ดีฉันเห็นว่าครอบครัวของคุณกำลังใช้ * b + c ในเชิงคณิตศาสตร์ การกล่าวถึง "แผนก" นั้นหมายถึง "การเพิ่ม" หรือไม่?
Potato44

btw คุณเกิดการละเมิดสเป็คของคุณเองในขณะนี้ "การดำเนินการระดับที่คูณสอง Peano เลข" สิ่งที่คุณมีอยู่ในขณะนี้ไม่ได้ชั้นก็ไม่เกิดขึ้นจะเป็นของชนิดConstraintแม้ว่า ดังนั้นคุณควรอัปเดตข้อมูลจำเพาะหรือเปลี่ยนกลับเป็นแบบฟอร์มที่ใช้คลาสแทนคำพ้องความหมายประเภท ถ้าฉันจะใช้คำพ้องความหมายประเภทฉันจะได้คำตอบของฉันลงไปที่ 96 bytes ดังนั้นมันช่วยฉันได้มากกว่า byte อีกหนึ่งตัวฉัน
Potato44

@ Potato44 ฉันรู้สึกว่าห้องเรียนเป็นเพียงบางสิ่งบางอย่างที่มีความขัดแย้ง บางทีอาจเป็นเพราะการขาดความชัดเจนในคำถาม ฉันจะกลับไปใช้คำตอบที่ 115 แล้ว
Ad Hoc Garf Hunter
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.