“ coalgebra” หมายถึงอะไรในบริบทของการเขียนโปรแกรม


339

ฉันเคยได้ยินคำว่า "coalgebras" หลายครั้งในการเขียนโปรแกรมการทำงานและวงกลม PLT โดยเฉพาะอย่างยิ่งเมื่อการสนทนาเกี่ยวกับวัตถุ, comonads, เลนส์และอื่น ๆ Googling คำนี้ให้หน้าซึ่งให้คำอธิบายทางคณิตศาสตร์ของโครงสร้างเหล่านี้ซึ่งฉันเข้าใจยากมาก ใครช่วยอธิบายหน่อยได้ว่า coalgebras มีความหมายอย่างไรในบริบทของการเขียนโปรแกรมความสำคัญของพวกมันคืออะไรและพวกมันเกี่ยวข้องกับวัตถุและ comonads อย่างไร


21
ฉันขอแนะนำรูปแบบหนังสือที่ยอดเยี่ยมของ Jeremy Gibbons ใน FP: patternsinfp.wordpress.com และกระดาษที่เข้าใจได้ค่อนข้างมากของเขาว่า พวกเขาทั้งสองครอบคลุมถ่านหินในรูปแบบที่ค่อนข้างเข้มงวด (เมื่อเทียบกับตัวอย่างเช่นโพสต์บล็อก) แต่พวกเขาก็มีความเป็นตัวของตัวเองพอสมควรสำหรับคนที่รู้จัก Haskell เล็กน้อย
Kristopher Micinski

2
@ KristopherMicinski น่าสนใจมาก ขอบคุณ!
missingfaktor

คำตอบ:


474

algebras

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

จากนั้นพีชคณิตจะเป็นเพียงแค่ชนิดของτฟังก์ชันและข้อมูลเฉพาะตัว ฟังก์ชั่นเหล่านี้จะนำตัวเลขของการขัดแย้งของประเภทที่แตกต่างกันτและผลิตτ: uncurried (τ, τ,…, τ) → τพวกเขามองทุกคนชอบ พวกเขายังสามารถมี "ตัวตน" - องค์ประกอบτที่มีพฤติกรรมพิเศษกับบางฟังก์ชั่น

ตัวอย่างที่ง่ายที่สุดคือ monoid หนังสือเป็นชนิดใดτที่มีฟังก์ชั่นและตัวตนmappend ∷ (τ, τ) → τ mzero ∷ τตัวอย่างอื่น ๆ รวมถึงสิ่งต่าง ๆ เช่นกลุ่ม (ซึ่งก็เหมือนกับ monoids ยกเว้นด้วยinvert ∷ τ → τฟังก์ชั่นพิเศษ), แหวน, ขัดแตะและอื่น ๆ

ฟังก์ชั่นทั้งหมดใช้งานได้τแต่อาจมีความแตกต่างกัน เราสามารถเขียนสิ่งเหล่านี้ออกเป็นτⁿ → τที่ซึ่งτⁿแผนที่จะเป็นอันดับn τหนึ่ง วิธีนี้จะทำให้ความรู้สึกที่จะคิดว่าตัวตนในฐานะτ⁰ → τที่เป็นเพียงอันดับที่ว่างเปล่าτ⁰ ()ดังนั้นเราสามารถทำให้แนวคิดของพีชคณิตง่ายขึ้นได้ในขณะนี้: มันเป็นเพียงบางประเภทที่มีฟังก์ชั่นบางอย่างอยู่

พีชคณิตเป็นเพียงรูปแบบทั่วไปในวิชาคณิตศาสตร์ที่ "เอาเรื่องออก" เช่นเดียวกับที่เราทำกับรหัส ผู้คนสังเกตุเห็นว่าสิ่งที่น่าสนใจมากมายทั้ง monoids ดังกล่าวกลุ่ม lattices และอื่น ๆ - ทั้งหมดทำตามรูปแบบที่คล้ายกันดังนั้นพวกเขาจึงแยกออก ข้อดีของการทำเช่นนี้เหมือนกับในการเขียนโปรแกรม: มันสร้างการพิสูจน์ซ้ำได้และทำให้การใช้เหตุผลบางประเภทง่ายขึ้น

F-Algebras

อย่างไรก็ตามเราไม่ได้ทำแฟคตอริ่ง จนถึงตอนนี้เรามีฟังก์ชั่นτⁿ → τมากมาย เราสามารถทำเคล็ดลับที่เป็นระเบียบเพื่อรวมพวกมันทั้งหมดเข้าเป็นฟังก์ชันเดียว โดยเฉพาะอย่างยิ่งลักษณ์ให้ของที่ monoids: เรามีและmappend ∷ (τ, τ) → τ mempty ∷ () → τเราสามารถเปิดเหล่านี้เป็นฟังก์ชั่นเดียวโดยใช้ผลรวม EitherTYPE- มันจะมีลักษณะเช่นนี้:

op  Monoid τ  Either (τ, τ) ()  τ
op (Left (a, b)) = mappend (a, b)
op (Right ())    = mempty

เราจริงสามารถใช้การเปลี่ยนแปลงนี้ซ้ำ ๆ เพื่อรวมทุกτⁿ → τฟังก์ชั่นเป็นหนึ่งเดียวสำหรับการใด ๆพีชคณิต (ในความเป็นจริงเราสามารถทำเช่นนี้สำหรับจำนวนของฟังก์ชั่นใด ๆa → τ, b → τและอื่น ๆ สำหรับการใด ๆ a, b,… .)

นี้จะช่วยให้เราพูดคุยเกี่ยวกับจีบเป็นชนิดτที่มีซิงเกิ้ลฟังก์ชั่นจากระเบียบของบางอย่างที่จะเป็นหนึ่งเดียวEither τสำหรับ monoids ระเบียบนี้คือ: Either (τ, τ) (); สำหรับกลุ่ม (ซึ่งมีการเสริมτ → τการดำเนินงาน) Either (Either (τ, τ) τ) ()ก็: มันเป็นประเภทที่แตกต่างกันสำหรับโครงสร้างที่แตกต่างกัน ดังนั้นสิ่งเหล่านี้มีอะไรเหมือนกัน? สิ่งที่ชัดเจนที่สุดคือพวกเขาทั้งหมดเป็นเพียงผลรวมของผลิตภัณฑ์ - ประเภทข้อมูลเกี่ยวกับพีชคณิต ตัวอย่างเช่นสำหรับ monoids เราสามารถสร้างประเภทอาร์กิวเมนต์หนังสือที่เหมาะกับใด ๆ τหนังสือ:

data MonoidArgument τ = Mappend τ τ -- here τ τ is the same as (τ, τ)
                      | Mempty      -- here we can just leave the () out

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

มีอะไรพิเศษเกี่ยวกับประเภทเหล่านี้ทั้งหมด? พวกเขาทั้งหมดFunctors! เช่น:

instance Functor MonoidArgument where
  fmap f (Mappend τ τ) = Mappend (f τ) (f τ)
  fmap f Mempty        = Mempty

ดังนั้นเราสามารถสรุปความคิดเกี่ยวกับพีชคณิตของเราได้มากกว่าเดิม มันเป็นเพียงแค่บางชนิดτที่มีฟังก์ชั่นf τ → τสำหรับ ffunctor อันที่จริงแล้วเราสามารถเขียนสิ่งนี้เป็นประเภทของงานพิมพ์:

class Functor f  Algebra f τ where
  op  f τ  τ

นี้มักจะถูกเรียกว่า "F-พีชคณิต" เพราะมันกำหนดโดย Ffunctor ถ้าเราบางส่วนสามารถนำไปใช้ typeclasses class Monoid = Algebra MonoidArgumentเราสามารถกำหนดสิ่งที่ต้องการ

Coalgebras

ตอนนี้หวังว่าคุณคงเข้าใจดีว่าพีชคณิตคืออะไรและมันเป็นแค่ลักษณะทั่วไปของโครงสร้างพีชคณิตทั่วไป F-coalgebra คืออะไร? เพื่อนร่วมก็บอกว่ามันเป็น "คู่" ของพีชคณิต - นั่นคือเราเอาพีชคณิตแล้วพลิกลูกศรบางอัน ฉันเห็นลูกศรหนึ่งลูกในคำจำกัดความด้านบนดังนั้นฉันจะพลิกดูว่า:

class Functor f  CoAlgebra f τ where
  coop  τ  f τ

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

ชั้นเรียนและวัตถุ

หลังจากอ่านไปซักพักฉันคิดว่าฉันมีความคิดที่ดีเกี่ยวกับวิธีการใช้ coalgebras เพื่อเป็นตัวแทนของคลาสและวัตถุ เรามีประเภทCที่มีสถานะภายในของวัตถุที่เป็นไปได้ทั้งหมดในชั้นเรียน ชั้นเรียนนั้นเป็นถ่านหินมากกว่าCซึ่งระบุวิธีการและคุณสมบัติของวัตถุ

ดังแสดงในตัวอย่างพีชคณิตถ้าเรามีพวงของฟังก์ชั่นเหมือนa → τและb → τสำหรับการใด ๆa, b,…ที่เราสามารถรวมพวกเขาทั้งหมดลงในฟังก์ชั่นเดียวโดยใช้Eitherชนิดจำนวนเงินที่ คู่ "ความคิด" จะรวมพวงของการทำงานของชนิดτ → a, τ → bและอื่น ๆ เราสามารถทำได้โดยใช้ผลรวมคู่ - ประเภทผลิตภัณฑ์ เมื่อให้ทั้งสองฟังก์ชั่นด้านบน (เรียกว่าfและg) เราสามารถสร้างหนึ่งเดียวเช่น:

both  τ  (a, b)
both x = (f x, g x)

ประเภท(a, a)คือ functor ในแนวตรงไปตรงมาดังนั้นมันจึงเหมาะกับความคิดของเราเกี่ยวกับ F-coalgebra เคล็ดลับนี้ช่วยให้เราสามารถรวบรวมฟังก์ชั่นที่แตกต่างกันมากมายหรือสำหรับ OOP วิธีการให้เป็นฟังก์ชั่นประเภทτ → f τเดียว

องค์ประกอบประเภทของเราCเป็นตัวแทนของสถานะภายในของวัตถุ หากวัตถุนั้นมีคุณสมบัติที่อ่านได้บางอย่างพวกเขาจะต้องสามารถพึ่งพาได้ Cวิธีที่ชัดเจนที่สุดในการทำเช่นนี้จะทำให้พวกเขาทำงานของ ดังนั้นถ้าเราต้องการคุณสมบัติความยาว (เช่นobject.length) เราจะมีฟังก์ชั่นC → Intเราจะมีฟังก์ชั่น

เราต้องการวิธีการที่สามารถโต้แย้งและแก้ไขสถานะ Cการทำเช่นนี้เราจำเป็นต้องใช้ทุกข้อโต้แย้งและการผลิตใหม่ ลองจินตนาการถึงsetPositionวิธีการที่จะใช้เวลาxและการประสานงาน:y object.setPosition(1, 2)มันจะเป็นแบบนี้: C → ((Int, Int) → C).

รูปแบบที่สำคัญที่นี่คือ "วิธีการ" และ "คุณสมบัติ" ของวัตถุนำวัตถุตัวเองเป็นอาร์กิวเมนต์แรกของพวกเขา นี่เหมือนกับselfพารามิเตอร์ใน Python และเหมือนกับนัยthisของภาษาอื่น ๆ อีกมากมาย coalgebra หลักเพียงสุนทรีย์พฤติกรรมของการเป็นselfพารามิเตอร์: นั่นคือสิ่งแรกCในการC → F Cเป็น

ดังนั้นเรามารวมกันทั้งหมด ลองนึกภาพคลาสที่มีpositionคุณสมบัติnameคุณสมบัติและsetPositionฟังก์ชัน:

class C
  private
    x, y  : Int
    _name : String
  public
    name        : String
    position    : (Int, Int)
    setPosition : (Int, Int)  C

เราต้องการสองส่วนเพื่อเป็นตัวแทนของคลาสนี้ อันดับแรกเราต้องแสดงสถานะภายในของวัตถุ ในกรณีนี้มันก็ถือสองInts Stringและ (นี่คือแบบของเราC) จากนั้นเราต้องหาค่าของพีชคณิตแทนคลาส

data C = Obj { x, y   Int
             , _name  String }

เรามีคุณสมบัติสองอย่างที่จะเขียน มันเป็นเรื่องเล็กน้อย:

position  C  (Int, Int)
position self = (x self, y self)

name  C  String
name self = _name self

ตอนนี้เราเพียงแค่ต้องสามารถอัปเดตตำแหน่ง:

setPosition  C  (Int, Int)  C
setPosition self (newX, newY) = self { x = newX, y = newY }

นี่เป็นเหมือนคลาส Python ที่มีselfตัวแปรที่ชัดเจน ตอนนี้เรามีself →ฟังก์ชั่นมากมายเราต้องรวมมันเข้าไปในฟังก์ชั่นเดียวสำหรับพีชคณิต เราสามารถทำสิ่งนี้ด้วย tuple ง่าย ๆ :

coop  C  ((Int, Int), String, (Int, Int)  C)
coop self = (position self, name self, setPosition self)

ประเภท((Int, Int), String, (Int, Int) → c)สำหรับผู้ใด c - เป็นนักแสดงดังนั้นcoopจะมีรูปแบบที่เราต้องการ: Functor f ⇒ C → f C.

ป.ร. ให้ไว้นี้Cพร้อมกับcoopรูปแบบ coalgebra ซึ่งระบุชั้นที่ฉันให้ไว้ข้างต้น คุณสามารถดูว่าเราสามารถใช้เทคนิคเดียวกันนี้เพื่อระบุจำนวนวิธีและคุณสมบัติใด ๆ สำหรับวัตถุของเราได้อย่างไร

สิ่งนี้ทำให้เราใช้การใช้เหตุผลเชิงพีชคณิตเพื่อจัดการกับคลาส ตัวอย่างเช่นเราสามารถนำความคิดของ "F-coalgebra homomorphism" เพื่อเป็นตัวแทนการเปลี่ยนแปลงระหว่างชั้นเรียน นี่เป็นคำที่ทำให้เกิดเสียงที่น่ากลัวซึ่งหมายถึงการเปลี่ยนแปลงระหว่าง coalgebras ที่รักษาโครงสร้างไว้ สิ่งนี้ทำให้คิดเกี่ยวกับการแม็พคลาสกับคลาสอื่นได้ง่ายขึ้น

ในระยะสั้น F-coalgebra หมายถึงคลาสโดยมีคุณสมบัติและวิธีการที่ขึ้นอยู่กับselfพารามิเตอร์ที่มีสถานะภายในของแต่ละวัตถุ

หมวดหมู่อื่น ๆ

จนถึงตอนนี้เราได้พูดคุยเกี่ยวกับ algebras และ coalgebras เป็นประเภท Haskell พีชคณิตเป็นเพียงชนิดτที่มีฟังก์ชั่นf τ → τและ coalgebra เป็นเพียงชนิดที่มีฟังก์ชั่นττ → f τ

แต่ไม่มีอะไรจริงๆผูกความคิดเหล่านี้จะ Haskell ต่อ se ในความเป็นจริงพวกมันมักจะถูกนำเสนอในรูปของเซตและฟังก์ชันทางคณิตศาสตร์มากกว่าชนิดและฟังก์ชัน Haskell แน่นอนเราสามารถพูดคุยแนวคิดเหล่านี้ในทุกหมวดหมู่!

เราสามารถกำหนด F-algebra สำหรับบางหมวดหมู่Cได้ อันดับแรกเราต้อง functor F : C → Cใช่หรือไม่เพราะเป็นผู้endofunctor (ทุก Haskell Functors เป็นจริง endofunctors จากHask → Hask.) จากนั้นพีชคณิตเป็นเพียงวัตถุAจากที่มีซึ่มส์C F A → Acoalgebra A → F Aเป็นเช่นเดียวกับการยกเว้น

เราจะได้อะไรจากการพิจารณาหมวดหมู่อื่น ๆ ? เราสามารถใช้ความคิดเดียวกันในบริบทที่แตกต่างกัน เหมือนพระ ใน Haskell monad เป็นประเภทที่M ∷ ★ → ★มีการดำเนินการสามอย่าง:

map         β)  (M α  M β)
return    α  M α
join      M (M α)  M α

mapฟังก์ชั่นเป็นเพียงหลักฐานของความจริงที่ว่าเป็นM Functorดังนั้นเราจึงสามารถพูดได้ว่า monad เป็นเพียงนักแสดงที่มีสองปฏิบัติการ: returnและjoinและ

หมวดหมู่ของตัวเองเป็น Funisors ด้วย morphisms ระหว่างพวกเขาถูกเรียกว่า "การเปลี่ยนแปลงตามธรรมชาติ" การเปลี่ยนแปลงตามธรรมชาติเป็นเพียงวิธีในการแปลง functor หนึ่งไปยังอีกในขณะที่รักษาโครงสร้างของมัน นี่เป็นบทความที่ดีที่ช่วยอธิบายความคิด มันพูดถึงconcatซึ่งเป็นเพียงjoinสำหรับรายการ

ด้วย Haskell functors องค์ประกอบของสอง functors เป็น functor ตัวเอง ใน pseudocode เราสามารถเขียนสิ่งนี้:

instance (Functor f, Functor g)  Functor (f  g) where
  fmap fun x = fmap (fmap fun) x

นี้ช่วยให้เราคิดเกี่ยวกับการทำแผนที่จากjoin f ∘ f → fประเภทของการมีjoin ∀α. f (f α) → f αโดยสังหรณ์ใจเราสามารถดูว่าฟังก์ชั่นที่ถูกต้องสำหรับทุกประเภทαสามารถคิดว่าเป็นการเปลี่ยนแปลงของfสามารถจะคิดว่าเป็นการเปลี่ยนแปลงของ

returnเป็นการเปลี่ยนแปลงที่คล้ายกัน ∀α. α → f αประเภทของมันคือ มันดูแตกต่าง - คนแรกαไม่ใช่ "ใน" นักแสดง! อย่างมีความสุขเราสามารถแก้ไขสิ่งนี้ได้โดยการเพิ่ม functor ประจำตัวที่นั่น: ∀α. Identity α → f α. ดังนั้นreturnการเปลี่ยนแปลงIdentity → fคือ

ตอนนี้เราสามารถคิดเกี่ยวกับ monad เป็นเพียงพีชคณิตตามรอบ functor บางส่วนfกับการดำเนินงานและf ∘ f → f Identity → fมันดูไม่คุ้นเคยเหรอ? มันคล้ายกับ monoid ซึ่งเป็นประเภทτปฏิบัติการτ × τ → τและ() → τและ

ดังนั้น Monad ก็เหมือนกับ monoid ยกเว้นแทนที่จะมีประเภทเรามี functor มันเป็นพีชคณิตแบบเดียวกันในหมวดหมู่อื่น (นี่คือที่วลี "monad เป็นเพียง monoid ในหมวดหมู่ของ endofunctors" มาจากเท่าที่ฉันรู้)

ตอนนี้เรามีทั้งสองการดำเนินงาน: และf ∘ f → f Identity → fเพื่อให้ได้ coalgebra ที่สอดคล้องกันเราแค่พลิกลูกศร นี้จะช่วยให้เราทั้งสองดำเนินการใหม่และf → f ∘ f f → Identityเราสามารถทำให้พวกเขาเป็นประเภท Haskell โดยการเพิ่มตัวแปรประเภทดังกล่าวข้างต้นให้เราและ∀α. f α → f (f α) ∀α. f α → αดูเหมือนว่าคำจำกัดความของ comonad:

class Functor f  Comonad f where
  coreturn  f α  α
  cojoin    f α  f (f α)

ดังนั้น comonad เป็นแล้วcoalgebraในหมวดหมู่ของ endofunctors


45
มันมีค่าอย่างไม่น่าเชื่อ ฉันจัดการคลุมเครือเกี่ยวกับธุรกิจเกี่ยวกับพีชคณิต F ทั้งหมดนี้จากการอ่านและตัวอย่าง (เช่นจากการเห็นการใช้งานกับ catamoprhisms) แต่นี่ก็ชัดเจนสำหรับฉัน ขอบคุณ!
Luis Casillas

28
นี่คือคำอธิบายที่ดี
Edward KMETT

5
@EdwardKmett: ขอบคุณ สิ่งที่ฉันเพิ่มเกี่ยวกับชั้นเรียนและวัตถุตกลงไหม? ฉันอ่านแค่วันนี้เท่านั้น แต่ดูเหมือนสมเหตุสมผลแล้ว
Tikhon Jelvis

7
สำหรับสิ่งที่มีค่า: "หมวดหมู่ของ endofunctors" ที่นี่เป็นหมวดหมู่ที่มีวัตถุที่เป็น endofunctors ในบางหมวดหมู่และลูกศรมีการเปลี่ยนแปลงตามธรรมชาติมากขึ้น นี่คือหมวดหมู่ monoidal โดยมีองค์ประกอบของ functor ที่สอดคล้องกับ(,)และ functor ประจำตัว()ของ วัตถุ monoid ภายในประเภท monoidal เป็นวัตถุที่มีลูกศรที่สอดคล้องกับพีชคณิต monoid ของคุณซึ่งอธิบายวัตถุ monoid ใน Hask ที่มีประเภทผลิตภัณฑ์เป็นโครงสร้าง monoidal วัตถุ monoid ในหมวดหมู่ของ endofunctors บน C คือ monad บน C ดังนั้นใช่ความเข้าใจของคุณถูกต้อง :]
CA McCann

8
นั่นคือตอนจบที่ยิ่งใหญ่!
jdinunzio

85

F-algebras และ F-coalgebras เป็นโครงสร้างทางคณิตศาสตร์ซึ่งเป็นเครื่องมือในการให้เหตุผลเกี่ยวกับประเภทอุปนัย (หรือประเภทแบบเรียกซ้ำ )

F-จีบ

เราจะเริ่มด้วย F-algebras ก่อน ฉันจะพยายามให้ง่ายที่สุด

ฉันเดาว่าคุณรู้ว่าประเภท recursive คืออะไร ตัวอย่างเช่นนี่เป็นประเภทสำหรับรายการจำนวนเต็ม:

data IntList = Nil | Cons (Int, IntList)

เห็นได้ชัดว่ามันซ้ำ - แน่นอนความหมายของมันหมายถึงตัวเอง คำจำกัดความของมันประกอบด้วยสองตัวสร้างข้อมูลซึ่งมีประเภทต่อไปนี้:

Nil  :: () -> IntList
Cons :: (Int, IntList) -> IntList

โปรดทราบว่าฉันได้เขียนประเภทของการNilเป็นไม่เพียง() -> IntList IntListในความเป็นจริงประเภทเหล่านี้เทียบเท่าจากมุมมองทางทฤษฎีเพราะ()ประเภทมีเพียงคนเดียวที่อาศัยอยู่

หากเราเขียนลายเซ็นของฟังก์ชั่นเหล่านี้ในแบบที่เป็นทฤษฎีมากกว่านี้เราก็จะได้

Nil  :: 1 -> IntList
Cons :: Int × IntList -> IntList

โดยที่1เป็นชุดของหน่วย (ชุดที่มีองค์ประกอบหนึ่ง) และA × Bการดำเนินการเป็นผลิตภัณฑ์แบบครอสของสองชุดAและB(นั่นคือชุดของคู่(a, b)ที่aผ่านองค์ประกอบทั้งหมดของAและbผ่านองค์ประกอบทั้งหมดของB )

สหภาพเคลื่อนของสองชุดAและBเป็นชุดA | Bซึ่งเป็นสหภาพของชุดและ{(a, 1) : a in A} {(b, 2) : b in B}โดยพื้นฐานแล้วมันเป็นชุดขององค์ประกอบทั้งหมดจากทั้งสองAและBด้วยการทำเครื่องหมายองค์ประกอบแต่ละรายการว่าเป็นของอย่างใดอย่างหนึ่งAหรือBดังนั้นเมื่อเราเลือกองค์ประกอบใด ๆ จากA | Bเราจะรู้ทันทีว่าองค์ประกอบนี้มาจากAหรือจากBหรือจาก

เราสามารถ 'เข้าร่วม' NilและConsฟังก์ชั่นดังนั้นพวกเขาจะสร้างฟังก์ชั่นเดียวที่ทำงานในชุด1 | (Int × IntList):

Nil|Cons :: 1 | (Int × IntList) -> IntList

แน่นอนถ้าNil|Consฟังก์ชั่นถูกนำไปใช้กับ()มูลค่า (ซึ่งเห็นได้ชัดว่าเป็นของการ1 | (Int × IntList)ตั้งค่า) แล้วมันจะทำงานเหมือนว่ามันเป็นNil; หากNil|Consนำไปใช้กับค่าประเภทใด ๆ(Int, IntList)(ค่าดังกล่าวยังอยู่ในชุด1 | (Int × IntList)มันจะทำงานเป็นConsก็จะทำงานเป็น

พิจารณาประเภทข้อมูลอื่น:

data IntTree = Leaf Int | Branch (IntTree, IntTree)

มันมีตัวสร้างต่อไปนี้:

Leaf   :: Int -> IntTree
Branch :: (IntTree, IntTree) -> IntTree

ซึ่งยังสามารถรวมเข้าเป็นฟังก์ชันเดียว:

Leaf|Branch :: Int | (IntTree × IntTree) -> IntTree

จะเห็นได้ว่าjoinedฟังก์ชั่นทั้งสองนี้มีประเภทที่คล้ายกัน

f :: F T -> T

ซึ่งFเป็นรูปแบบของการเปลี่ยนแปลงที่ใช้ประเภทของเราและให้ประเภทที่ซับซ้อนมากขึ้นซึ่งประกอบด้วยxและ|การดำเนินงานประเพณีTและประเภทอื่น ๆ ตัวอย่างเช่นสำหรับIntListและIntTree Fมีลักษณะดังนี้:

F1 T = 1 | (Int × T)
F2 T = Int | (T × T)

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

ตอนนี้เราสามารถนิยาม F-algebra ได้ F-พีชคณิตเป็นเพียงคู่(T, f)ที่Tเป็นชนิดบางและเป็นหน้าที่ของประเภทf f :: F T -> Tในตัวอย่างของเรา F-จีบรามีและ(IntList, Nil|Cons) (IntTree, Leaf|Branch)อย่างไรก็ตามโปรดทราบว่าถึงแม้ว่าfฟังก์ชั่นประเภทนั้นจะเหมือนกันสำหรับ F แต่ละตัวTและfสามารถกำหนดเองได้ตามใจชอบ ตัวอย่างเช่น(String, g :: 1 | (Int x String) -> String)หรือ(Double, h :: Int | (Double, Double) -> Double)สำหรับบางคนgและhยังเป็น F-algebras สำหรับ F ที่เกี่ยวข้อง

หลังจากนั้นเราสามารถแนะนำโฮโมมอร์ฟิซึมของ F-algebraแล้วเริ่มต้น F-algebrasซึ่งมีคุณสมบัติที่มีประโยชน์มาก ในความเป็นจริง(IntList, Nil|Cons)เป็น F1- พีชคณิตเริ่มต้นและ(IntTree, Leaf|Branch)เริ่มต้นเป็น F2- พีชคณิตเริ่มต้น ฉันจะไม่แสดงคำจำกัดความที่แน่นอนของข้อกำหนดและคุณสมบัติเหล่านี้เนื่องจากมีความซับซ้อนและเป็นนามธรรมมากกว่าที่ต้องการ

อย่างไรก็ตามความจริงที่ว่า(IntList, Nil|Cons)คือพีชคณิต F ทำให้เราสามารถนิยามfoldฟังก์ชันคล้ายกับประเภทนี้ได้ ดังที่คุณทราบการพับเป็นชนิดของการดำเนินการที่แปลงประเภทข้อมูลแบบเรียกซ้ำในค่า จำกัด อันเดียว ตัวอย่างเช่นเราสามารถพับรายการจำนวนเต็มเป็นค่าเดียวซึ่งเป็นผลรวมขององค์ประกอบทั้งหมดในรายการ:

foldr (+) 0 [1, 2, 3, 4] -> 1 + 2 + 3 + 4 = 10

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

ต่อไปนี้เป็นลายเซ็นของfoldrฟังก์ชั่น:

foldr :: ((a -> b -> b), b) -> [a] -> b

โปรดทราบว่าฉันใช้วงเล็บปีกกาเพื่อแยกอาร์กิวเมนต์สองตัวแรกจากอาร์กิวเมนต์สุดท้าย นี่ไม่ใช่foldrฟังก์ชั่นที่แท้จริงแต่มันเป็น isomorphic กับมัน (นั่นคือคุณสามารถได้รับอย่างใดอย่างหนึ่งจากที่อื่นและในทางกลับกัน) นำไปใช้บางส่วนfoldrจะมีลายเซ็นต่อไปนี้:

foldr ((+), 0) :: [Int] -> Int

เราจะเห็นว่านี่เป็นฟังก์ชั่นที่รับรายการจำนวนเต็มและส่งกลับจำนวนเต็มเดียว ให้มีกำหนดฟังก์ชั่นดังกล่าวในแง่ของเราIntListประเภท

sumFold :: IntList -> Int
sumFold Nil         = 0
sumFold (Cons x xs) = x + sumFold xs

เราจะเห็นว่าฟังก์ชั่นนี้ประกอบด้วยสองส่วน: ส่วนแรกกำหนดพฤติกรรมของฟังก์ชั่นนี้ในNilส่วนของIntListและส่วนที่สองกำหนดพฤติกรรมของฟังก์ชั่นในConsส่วน

ทีนี้สมมติว่าเรากำลังเขียนโปรแกรมไม่ได้อยู่ใน Haskell แต่ในบางภาษาที่อนุญาตให้ใช้พีชคณิตประเภทโดยตรงในลายเซ็นประเภท (ดีเทคนิค Haskell อนุญาตให้ใช้ประเภทพีชคณิตผ่าน tuples และEither a bประเภทข้อมูล แต่สิ่งนี้จะนำไปสู่ ​​verbosity ที่ไม่จำเป็น) พิจารณาฟังก์ชั่น:

reductor :: () | (Int × Int) -> Int
reductor ()     = 0
reductor (x, s) = x + s

จะเห็นได้ว่าreductorเป็นฟังก์ชั่นของประเภทF1 Int -> Intเช่นเดียวกับในคำจำกัดความของ F-algebra! อันที่จริงทั้งคู่(Int, reductor)เป็น F1- พีชคณิต

เพราะIntListเป็น F1- พีชคณิตเริ่มต้นสำหรับแต่ละประเภทTและสำหรับแต่ละฟังก์ชั่นr :: F1 T -> Tมีฟังก์ชั่นที่เรียกว่าcatamorphismสำหรับrซึ่งแปลงIntListเป็นTและฟังก์ชั่นดังกล่าวเป็นเอกลักษณ์ อันที่จริงในตัวอย่างของเราสำหรับ catamorphism มีreductor sumFoldสังเกตได้อย่างไรreductorและsumFoldคล้ายกัน: พวกเขามีโครงสร้างเกือบเหมือนกัน! ในการใช้พารามิเตอร์reductorนิยามs(ประเภทที่สอดคล้องกับT) สอดคล้องกับการใช้งานผลลัพธ์ของการคำนวณของsumFold xsในsumFoldคำนิยาม

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

(append [4, 5, 6]) [1, 2, 3] = (foldr (:) [4, 5, 6]) [1, 2, 3] -> [1, 2, 3, 4, 5, 6]

นี่เป็นลักษณะของเราIntList:

appendFold :: IntList -> IntList -> IntList
appendFold ys ()          = ys
appendFold ys (Cons x xs) = x : appendFold ys xs

อีกครั้งลองเขียน reductor:

appendReductor :: IntList -> () | (Int × IntList) -> IntList
appendReductor ys ()      = ys
appendReductor ys (x, rs) = x : rs

appendFoldเป็น catamorphism สำหรับappendReductorที่แปลงลงในIntListIntList

ดังนั้นโดยพื้นฐานแล้ว F-algebras ทำให้เราสามารถกำหนด 'folds' ในโครงสร้างข้อมูลแบบเรียกซ้ำได้นั่นคือการดำเนินการที่ลดโครงสร้างของเราให้มีค่าบางอย่าง

F-coalgebras

F-coalgebras เรียกว่าคำว่า 'dual' สำหรับ F-algebras มันช่วยให้เราสามารถกำหนดunfoldsประเภทข้อมูลแบบเรียกซ้ำได้นั่นคือวิธีการสร้างโครงสร้างแบบเรียกซ้ำจากค่าบางค่า

สมมติว่าคุณมีประเภทต่อไปนี้:

data IntStream = Cons (Int, IntStream)

นี่คือกระแสจำนวนเต็มของอนันต์ มันสร้างเพียงอย่างเดียวมีประเภทต่อไปนี้:

Cons :: (Int, IntStream) -> IntStream

หรือในแง่ของชุด

Cons :: Int × IntStream -> IntStream

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

head :: IntStream -> Int
head (Cons (x, xs)) = x

tail :: IntStream -> IntStream
tail (Cons (x, xs)) = xs

คุณสามารถ 'เข้าร่วม' ฟังก์ชั่นเหล่านี้โดยธรรมชาติในฟังก์ชั่นประเภทเดียวIntStream -> Int × IntStream:

head&tail :: IntStream -> Int × IntStream
head&tail (Cons (x, xs)) = (x, xs)

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

g :: T -> F T

ที่Tเป็นชนิดบาง จากนี้ไปเราจะให้คำจำกัดความ

F1 T = Int × T

ตอนนี้F-coalgebraคือคู่(T, g)ที่Tเป็นชนิดและเป็นหน้าที่ของประเภทg g :: T -> F Tตัวอย่างเช่น(IntStream, head&tail)F1-coalgebra อีกครั้งเช่นเดียวกับใน F-algebras gและTสามารถเป็นกฎเกณฑ์ได้เช่นกัน(String, h :: String -> Int x String)ก็เป็น F1-coalgebra สำหรับบางชั่วโมง

ในบรรดา F-coalgebras มีสิ่งที่เรียกว่าอาคาร F-coalgebrasซึ่งเป็นคู่กับ F-algebras เริ่มต้น ตัวอย่างเช่นIntStreamเป็นเทอร์มินัล F-coalgebra ซึ่งหมายความว่าสำหรับทุกประเภทTและทุกฟังก์ชั่นp :: T -> F1 Tที่มีอยู่ฟังก์ชั่นที่เรียกว่าanamorphismซึ่งจะแปลงTไปIntStreamและฟังก์ชั่นดังกล่าวมีความเป็นเอกลักษณ์

พิจารณาฟังก์ชั่นต่อไปนี้ซึ่งสร้างกระแสของจำนวนเต็มต่อเนื่องเริ่มต้นจากที่กำหนด:

nats :: Int -> IntStream
nats n = Cons (n, nats (n+1))

ตอนนี้ลองตรวจสอบฟังก์ชั่นnatsBuilder :: Int -> F1 Intนั่นคือnatsBuilder :: Int -> Int × Int:

natsBuilder :: Int -> Int × Int
natsBuilder n = (n, n+1)

อีกครั้งเราจะเห็นความคล้ายคลึงกันบางอย่างระหว่างและnats natsBuilderมันคล้ายกับการเชื่อมต่อที่เราสังเกตเห็นด้วย reductors และเท่าก่อนหน้านี้ natsเป็น anamorphism natsBuilderสำหรับ

อีกตัวอย่างหนึ่งคือฟังก์ชั่นที่รับค่าและฟังก์ชั่นแล้วส่งคืนสตรีมของแอปพลิเคชันที่ต่อเนื่องของฟังก์ชันเป็นค่า:

iterate :: (Int -> Int) -> Int -> IntStream
iterate f n = Cons (n, iterate f (f n))

ฟังก์ชั่นการสร้างมันเป็นหนึ่งในต่อไปนี้:

iterateBuilder :: (Int -> Int) -> Int -> Int × Int
iterateBuilder f n = (n, f n)

จากนั้นiterateเป็น anamorphism iterateBuilderสำหรับ

ข้อสรุป

ดังนั้นในระยะสั้น F-algebras อนุญาตให้กำหนด folds นั่นคือการดำเนินการที่ลดโครงสร้างแบบเรียกซ้ำลงในค่าเดียวและ F-coalgebras อนุญาตให้ทำตรงกันข้าม: สร้างโครงสร้างอนันต์ที่อาจเกิดขึ้นจากค่าเดียว

ในความเป็นจริงใน Haskell F-algebras และ F-coalgebras เหมือนกัน นี่คือคุณสมบัติที่ดีมากซึ่งเป็นผลมาจากการปรากฏตัวของ 'ด้านล่าง' ค่าในแต่ละประเภท ดังนั้นใน Haskell สามารถสร้างทั้งการพับและการกางออกได้สำหรับการเกิดซ้ำทุกประเภท อย่างไรก็ตามแบบจำลองทางทฤษฎีที่อยู่เบื้องหลังสิ่งนี้มีความซับซ้อนมากกว่าแบบที่ฉันได้นำเสนอไว้ด้านบนดังนั้นฉันจงใจหลีกเลี่ยงมัน

หวังว่านี่จะช่วยได้


ประเภทและคำจำกัดความของappendReductorรูปลักษณ์แปลก ๆ และไม่ได้ช่วยให้ฉันเห็นรูปแบบที่นั่น ... :) คุณตรวจสอบอีกครั้งว่ามันถูกต้องหรือไม่ .. ประเภท Reductor ควรมีลักษณะอย่างไรโดยทั่วไป? ในคำจำกัดความของที่rนั่นจะถูกF1กำหนดโดย IntList หรือเป็น F โดยพลการ
Max Galkin

37

การอ่านบทความเกี่ยวกับการสอนเกี่ยวกับพีชคณิต (co) และการเหนี่ยวนำ (co)ควรจะให้ข้อมูลเชิงลึกเกี่ยวกับพีชคณิตร่วมในสาขาวิทยาศาสตร์คอมพิวเตอร์

ด้านล่างนี้เป็นการอ้างอิงเพื่อโน้มน้าวคุณ

โดยทั่วไปโปรแกรมในภาษาการเขียนโปรแกรมบางอย่างจะจัดการกับข้อมูล ในระหว่างการพัฒนาวิทยาการคอมพิวเตอร์ในช่วงสองสามทศวรรษที่ผ่านมาเป็นที่ชัดเจนว่าคำอธิบายที่เป็นนามธรรมของข้อมูลเหล่านี้เป็นที่ต้องการตัวอย่างเช่นเพื่อให้แน่ใจว่าโปรแกรมหนึ่งไม่ได้ขึ้นอยู่กับการแสดงข้อมูลที่ทำงาน นอกจากนี้ความเป็นนามธรรมดังกล่าวอำนวยความสะดวกในการพิสูจน์ความถูกต้อง
ความปรารถนานี้นำไปสู่การใช้วิธีการทางพีชคณิตในวิทยาการคอมพิวเตอร์ในสาขาที่เรียกว่าข้อมูลจำเพาะเกี่ยวกับพีชคณิตหรือทฤษฎีชนิดข้อมูลนามธรรม วัตถุประสงค์ของการศึกษาคือประเภทข้อมูลในตัวเองโดยใช้แนวคิดของเทคนิคที่คุ้นเคยจากพีชคณิต ชนิดข้อมูลที่ใช้โดยนักวิทยาศาสตร์คอมพิวเตอร์มักจะถูกสร้างขึ้นจากการรวบรวมการดำเนินการ (นวกรรมิก) และด้วยเหตุผลนี้เองที่ "การเริ่มต้น" ของ algebras มีบทบาทสำคัญเช่นนี้
เทคนิคพีชคณิตมาตรฐานได้พิสูจน์แล้วว่ามีประโยชน์ในการเก็บข้อมูลสำคัญต่างๆของโครงสร้างข้อมูลที่ใช้ในวิทยาการคอมพิวเตอร์ แต่มันกลับกลายเป็นว่าเป็นการยากที่จะอธิบายพีชคณิตเกี่ยวกับโครงสร้างพลวัตที่เกิดขึ้นในการคำนวณ โครงสร้างดังกล่าวมักจะเกี่ยวข้องกับความคิดของรัฐซึ่งสามารถเปลี่ยนได้หลายวิธี วิธีการอย่างเป็นทางการสำหรับระบบพลวัตของรัฐนั้นมักใช้ประโยชน์จากระบบออโตมาตะหรือทรานซิชัน
ในช่วงทศวรรษที่ผ่านมาความเข้าใจที่ลึกซึ้งขึ้นเรื่อย ๆ ว่าระบบของรัฐนั้นไม่ควรอธิบายว่าเป็นจีบราส์ แต่เป็นที่รู้จักกันในชื่อ นี่เป็นอัลกอริธึมคู่อย่างเป็นทางการซึ่งจะแม่นยำในการสอนนี้ คุณสมบัติคู่ของ "เริ่มต้น" สำหรับ algebras คือวาระสุดท้ายกลายเป็นสิ่งสำคัญสำหรับ co-algebras ดังกล่าว และหลักการการใช้เหตุผลเชิงตรรกะที่จำเป็นสำหรับ algebras สุดท้ายเช่นนั้นไม่ใช่การเหนี่ยวนำ แต่เป็นการเหนี่ยวนำร่วม


โหมโรงเกี่ยวกับทฤษฎีหมวดหมู่ ทฤษฎีหมวดหมู่ควรเปลี่ยนชื่อทฤษฎีของ functors เนื่องจากหมวดหมู่เป็นสิ่งที่เราต้องกำหนดเพื่อกำหนดฟังก์ชั่น (ยิ่งไปกว่านั้นฟังก์ชั่นการทำงานเป็นสิ่งที่เราต้องกำหนดเพื่อกำหนดการเปลี่ยนแปลงตามธรรมชาติ)

functor คืออะไร? มันเป็นการเปลี่ยนแปลงจากชุดหนึ่งไปอีกชุดหนึ่งซึ่งรักษาโครงสร้างเอาไว้ (สำหรับรายละเอียดเพิ่มเติมมีคำอธิบายที่ดีมากมายในเน็ต)

พีชคณิต F คืออะไร? มันเป็นพีชคณิตของ functor มันเป็นเพียงการศึกษาความเป็นสากลของ functor

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

ทำไมต้อง F-co-algebra โปรแกรมเป็นแบบคู่โดยสาระสำคัญตามที่อธิบายโดยข้อมูลและพวกเขาดำเนินการกับมัน จากนั้นข้อมูลส่วนใหญ่ที่เขียนโปรแกรมและทำการเปลี่ยนแปลงสามารถดูได้สองทาง

  • ข้อมูลที่สามารถกำหนดเป็นข้อมูลที่กำลังประมวลผลโดยโปรแกรม
  • สถานะที่สามารถกำหนดเป็นข้อมูลที่ถูกแบ่งปันโดยโปรแกรม

จากนั้นในขั้นตอนนี้ฉันอยากจะบอกว่า

  • F-algebra เป็นการศึกษาการเปลี่ยนแปลงของ functorial ที่ทำหน้าที่แทนจักรวาลของ Data (ดังที่นิยามไว้ที่นี่)
  • F-co-algebras เป็นการศึกษาการเปลี่ยนแปลง functorial ที่กระทำต่อจักรวาลของรัฐ (ตามที่นิยามไว้ที่นี่)

ในช่วงชีวิตของโปรแกรมข้อมูลและสถานะอยู่ร่วมกันและพวกมันจะทำให้กันและกัน พวกเขาเป็นคู่


5

ฉันจะเริ่มต้นด้วยสิ่งต่าง ๆ ที่เกี่ยวข้องกับการเขียนโปรแกรมแล้วเพิ่มเนื้อหาคณิตศาสตร์บางอย่างเพื่อให้มันเป็นรูปธรรมและเป็นไปตามพื้นดินเท่าที่จะทำได้


ลองอ้างนักวิทยาศาสตร์คอมพิวเตอร์บางคนเกี่ยวกับการสร้างเหรียญ ...

http://www.cs.umd.edu/~micinski/posts/2012-09-04-on-understanding-coinduction.html

การเหนี่ยวนำเป็นเรื่องเกี่ยวกับข้อมูล จำกัด การเหนี่ยวนำร่วมเป็นเรื่องเกี่ยวกับข้อมูลที่ไม่มีที่สิ้นสุด

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

 let (pi : int list) = (* some function which computes the digits of
 π. *)

คอมพิวเตอร์ไม่สามารถจับπทั้งหมดได้เพราะมันมีหน่วยความจำไม่ จำกัด ! แต่สิ่งที่สามารถทำได้คือจัดโปรแกรม จำกัด ซึ่งจะสร้างการขยายตัวแบบ arbit ตามที่คุณต้องการ ตราบใดที่คุณใช้ชิ้นส่วน จำกัด ของรายการคุณสามารถคำนวณกับรายการที่ไม่มีที่สิ้นสุดได้มากเท่าที่คุณต้องการ

อย่างไรก็ตามพิจารณาโปรแกรมต่อไปนี้:

let print_third_element (k : int list) =   match k with
     | _ :: _ :: thd :: tl -> print thd


 print_third_element pi

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

http://adam.chlipala.net/cpdt/html/Coinductive.html

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

http://www.alexandrasilva.org/#/talks.html ตัวอย่างของ coalgebras โดย Alexandra Silva


เกี่ยวข้องกับบริบททางคณิตศาสตร์โดยรอบกับงานเขียนโปรแกรมตามปกติ

"พีชคณิต" คืออะไร?

โครงสร้างพีชคณิตโดยทั่วไปดูเหมือนว่า:

  1. Stuff
  2. สิ่งที่สามารถทำได้

สิ่งนี้ควรฟังดูเหมือนวัตถุที่มี 1. คุณสมบัติและ 2. วิธีการ หรือดียิ่งขึ้นมันควรฟังเหมือนลายเซ็นประเภท

ตัวอย่างทางคณิตศาสตร์มาตรฐาน ได้แก่ monoid ⊃ group ⊃ vector-space ⊃ "an algebra" Monoids เป็นเหมือนออโตมาตะ: ลำดับของคำกริยา (เช่น, f.g.h.h.nothing.f.g.f) gitบันทึกที่มักจะเพิ่มประวัติศาสตร์และไม่เคยลบมันจะเป็นหนังสือ แต่ไม่กลุ่ม หากคุณเพิ่มผู้รุกราน (เช่นจำนวนลบ, เศษส่วน, ราก, ลบประวัติสะสม, ไม่ทำลายกระจกแตก) คุณจะได้รับกลุ่ม

กลุ่มประกอบด้วยสิ่งต่าง ๆ ที่สามารถเพิ่มหรือลบเข้าด้วยกันได้ ตัวอย่างเช่นDurationสามารถรวมเข้าด้วยกัน (แต่Dateไม่สามารถทำได้) ระยะเวลาอยู่ในเวกเตอร์สเปซ (ไม่ใช่เฉพาะกลุ่ม) เพราะพวกเขาสามารถถูกปรับขนาดด้วยตัวเลขภายนอกได้ (ลายเซ็นประเภทของscaling :: (Number,Duration) → Duration)

algebras ⊂เวกเตอร์พื้นที่ยังสามารถทำสิ่งอื่น: m :: (T,T) → Tมีบาง เรียกสิ่งนี้ว่า "การคูณ" หรือไม่เพราะเมื่อคุณออกไปIntegersแล้วจะไม่ชัดเจนว่า "การคูณ" (หรือ"การยกกำลัง" ) ควรจะเป็นเท่าไหร่

(นี่คือเหตุผลที่ผู้คนมองไปที่คุณสมบัติสากล (หมวดหมู่เชิงทฤษฎี): เพื่อบอกพวกเขาว่าการคูณจะต้องทำหรือเป็นอย่างไร :

คุณสมบัติสากลของผลิตภัณฑ์ )


Algebras → Coalgebras

การคอมมิชชันนั้นง่ายกว่าที่จะนิยามในลักษณะที่รู้สึกว่าไม่มีกฎเกณฑ์มากกว่าการคูณเพราะการออกไปจากT → (T,T)คุณสามารถทำซ้ำองค์ประกอบเดียวกันได้ ("แผนที่เส้นทแยงมุม" - เหมือนกับเมทริกซ์ / ตัวดำเนินการแนวทแยงในทฤษฎีสเปกตรัม)

Counit นั้นมักจะเป็นร่องรอย (ผลรวมของเส้นทแยงมุม) แม้ว่าสิ่งที่สำคัญคือสิ่งที่ counit ของคุณทำอีกครั้ง traceเป็นเพียงคำตอบที่ดีสำหรับเมทริกซ์

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


การทำให้เชื่อง (ยกเลิก) ข้อมูลที่มีโครงสร้าง

นักคณิตศาสตร์อาจทำตัวเป็นแบบอย่างที่สนุกเหมือนTQFTในขณะที่โปรแกรมเมอร์ต้องต่อสู้ด้วย

  • วันที่ / ครั้ง ( + :: (Date,Duration) → Date)
  • สถานที่ ( Paris(+48.8567,+2.3508)! มันเป็นรูปร่างไม่ใช่จุด)
  • JSON ที่ไม่มีโครงสร้างซึ่งควรจะสอดคล้องกันในบางแง่มุม
  • XML ผิด แต่ปิด
  • ข้อมูล GIS ที่ซับซ้อนอย่างเหลือเชื่อซึ่งน่าพึงพอใจต่อความสัมพันธ์ที่สมเหตุสมผล
  • นิพจน์ทั่วไปซึ่งมีความหมายกับคุณ แต่มีความหมายน้อยกว่ามากสำหรับ Perl
  • CRM ที่ควรถือหมายเลขโทรศัพท์ของผู้บริหารและสถานที่บ้านพักตากอากาศทั้งหมดชื่อภรรยาและลูกของเขาวันเกิดและของขวัญก่อนหน้านี้ทั้งหมดซึ่งแต่ละรายการควรตอบสนองความสัมพันธ์ "ชัดเจน" (ชัดเจนต่อลูกค้า) ซึ่งเหลือเชื่อ ยากที่จะเขียนโค้ด
  • .....

นักวิทยาศาสตร์คอมพิวเตอร์เมื่อพูดถึง coalgebras มักจะมีการปฏิบัติงานในใจเช่นผลิตภัณฑ์คาร์ทีเซียน ฉันเชื่อว่านี่คือสิ่งที่ผู้คนหมายถึงเมื่อพวกเขาพูดเช่น "Algebras เป็น coalgebras ใน Haskell" แต่เท่าที่โปรแกรมเมอร์ต้องซับซ้อนของรูปแบบข้อมูลประเภทเช่นPlace, Date/TimeและCustomerและอื่นทำให้โมเดลเหล่านั้นดูเป็นเหมือนโลกแห่งความจริง (หรืออย่างน้อยในมุมมองของผู้ใช้ปลายทางของโลกแห่งความจริง) เป็นไปได้ผมเชื่อว่า duals, อาจมีประโยชน์นอกเหนือจากโลกที่ตั้งไว้เท่านั้น

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