DEV Community

armariya
armariya

Posted on • Originally published at Medium on

ปฐมบท ก้าวแรกสู่ Category Theory

สวัสดีครับ บอกตามตรงว่าหัวข้อนี้เนี่ย ผมเพิ่งจะก้าวเข้ามาเหมือนกันนะครับ อาจจะมีผิดถูกบ้าง แต่จะพยายามให้ถูกที่สุดนะครับ โดยผมจะอ้างอิงจากหนังสือ 'Category Theory for Programmers' ของ 'Bartosz Milewski' เป็นหลักนะครับ เพราะว่าผมกำลังอ่านเล่มนี้อยู่ แล้วพอได้ข้อมูลมาก้อนนึง ผมก็จะพยายามมาเขียนบทความเรื่อย ๆ นะครับ

หน้าแรกของหนังสือ Category Theory for Programmers

สำหรับ Category Theory คืออะไรนั้น ผมขออธิบายสั้น ๆ ว่ามันคือสาขาหนึ่งใน Math ที่เหมาะกับสมองของ Programmer มาก ๆ โดย Category Theory เนี่ย แทนที่เราจะมองเจาะลึกรายละเอียดลงในแต่ละอย่าง แต่มันกลับผลักดันให้เราเลือกที่จะมองภาพรวมของสิ่งต่าง ๆ มากกว่า เอ้อเกือบลืมบอกไป ในบล็อกนี้ผมจะเขียนหรือยกตัวอย่างด้วยภาษา Haskell เป็นหลักนะครับ จะค่อย ๆ Introduce เขาสู่ทุกคนไป ถ้าใครไม่เคยเขียนมาก่อนนะครับ

Category: The Essence of Composition

ตัว Category เองมี Concept ที่ง่าย ๆ มากคือ Category ประกอบไปด้วย object(s) ที่มี arrow ที่เชื่อมกันระหว่าง object(s) โดยปกติเวลาเราวาดเรามักจะแทนพวก object(s) ด้วยวงกลมหรือจุดเพียงจุดเดียวก็ได้ แล้วตัว arrow ก็คือ arrow จริง ๆ อะ เป็นลูกศรที่เชื่อม object(s) เข้าด้วยกัน โดยจากชื่อข้างบนเลยก็คือ The Essence of Composition หรือก็คือ Composition เป็นหัวใจหลักของ Category กล่าวคือการ compose ของ arrow ถ้าเรามี arrow จาก object A ไป object B และเรามี arrow จาก object B ไป object C เราสามารถบอกได้ว่ามันจะต้องมี arrow จาก A ไป C แน่ ๆ ที่เกิดจากการ compose กันของ 2 arrows

A, B, C แทน object ส่วนลูกศรนั่นคือ arrow (สามารถเรียกได้ว่า morphism) arrow f กับ g ส่วนเส้นประม่วงคือ เส้นที่เกิดจากการ compose กันของสอง arrow เป็น arrow ใหม่ เรียกว่า f∘gอ่านว่า ‘f after g’

สับสนล่ะสิ?? 555 ไม่ต้องแปลกใจครับ เป็นเรื่องปกติมาก ๆ ที่จะมึน ๆ แต่ด้วยความที่เราเป็น Programmer ทำให้เรามองเรื่องนี้ได้ง่ายขึ้นมาก ๆ ครับ โดยปกติแล้วพวกเราเหล่า Programmer อยู่ในโลกที่เรียกว่า ‘Category of Types” ถ้าเราลองเอาความหมายข้างบนมาแปลเป็นภาษา Programmer ก็คือ เราสามารถมองพวก object(s) ที่ว่าเนี่ยเป็นแต่ละ type ได้เช่น Int, String, Boolean อะไรแบบนั้น แล้วพวก arrow เนี่ยก็คือ function ที่เชื่อม object(s) พวกนี้เข้าด้วยกัน เช่น function ที่รับ Int เข้าไปแล้ว return String กลับมา ก็จะเป็น Int -> String เป็นหน้าตาประมาณนี้ ขอแวะกลับมาดู Haskell นิดนึงครับ ในกรณีนี้เราจะสามารถเขียนใน Haskell ได้ประมาณนี้

f :: Int -> String
Enter fullscreen mode Exit fullscreen mode

ข้างบนนี้อ่านว่า function f มี type เป็น Int -> String หรือก็คือรับ Int เข้าไป แล้ว return String กลับออกมานั่นเอง ที่นี้เรามาดูการ compose ของ arrow กัน สมมติเรามีแบบนี้

f :: String -> Int
g :: Int -> Bool

g.f :: String -> Bool
Enter fullscreen mode Exit fullscreen mode

จะเห็นว่าเรามีฟังก์ชัน f ที่รับ String เข้ามาแล้วส่ง Int กลับมา

และเรามีฟังก์ชัน g ที่รับ Int เข้ามาแล้วส่ง Bool กลับมา

ทีนี้เราจะเห็นอะไรแปลก ๆ ก็คือ g.f ตัว g.f นี่จะหมายถึง g compose กับ f โดยเราจะอ่านว่า ‘g after f’ หรือก็คือทำ f ก่อนแล้วค่อยทำ g นั่นเอง ซึ่งก็จะมี type เป็น String -> Bool เลย

แล้วอะไรถึงจะถือว่าเป็น Category?

การที่เราจะรู้ได้ว่าอะไรเป็น Category เนี่ย การ Compose ใน Category นั้น ๆ จะต้องมีคุณสมบัติทั้งหมดสองอย่างคือ

  • Composition Associative
  • Identity arrow

ถ้ามีครบทั้งสองอย่างแล้วเราจะถือว่าสิ่งนั้นเป็น Category โดยแต่ละอันคือ

Composition Associative

สมมติว่าถ้าคุณมี 3 arrow f, g และ h อยู่ ซึ่งสามารถ Compose กันได้แล้วเนี่ย ไม่ว่าจะใส่วงเล็บหรือไม่ใส่วงเล็บ ก็ไม่มีผลต่อการ Compose ถ้าเขียนให้ออกมาในรูปของสัญกรณ์คณิตศาศตร์แล้วจะได้แบบนี้

h∘(g∘f) = (h∘g)∘f = h∘g∘f
Enter fullscreen mode Exit fullscreen mode

จากรูปจะเห็นว่าไม่ว่าจะ compose อันไหนก่อนหรือ compose ทั้งหมดเลย ปลายทางก็ยังคงเหมือนกัน

Identity arrow

สำหรับทุก object ใน Category จะต้องมีอยู่ arrow นึงที่จะลูปเข้าหาตัวเอง ซึ่งหมายความว่าถ้าเราเอา arrow นี้ Compose เข้ากับ arrow อื่น ๆ จะต้องได้ arrow นั้น ๆ เสมอ ซึ่งเราจะเรียก arrow ที่รูปเข้าหาตัวเองว่า Identity arrow

ภาพของ identity arrow

ถ้าเราเขียนให้อยู่ในรูปของสัญกรณ์คณิตศาสตร์จะได้เป็น

IDA ∘ f = f
f ∘ IDA = f
Enter fullscreen mode Exit fullscreen mode

เราอาจจะคิดไม่ออกว่าถ้าอยู่ในรูปของ Function จะเป็นไง มันก็คือฟังก์ชันที่รับ Argument ใด ๆ เข้ามาแล้วจะ return Argument กลับไปนั่นเอง

Identity :: A => A
Identity x = x
Enter fullscreen mode Exit fullscreen mode

อันนี้ก็คือ identity function มี type เป็นรับอะไรมาก็ได้แล้วส่ง type เดิมกลับไป ถ้าเราจะเขียนในภาษาอื่นก็อาจจะต้องทำด้วย Generic Type อะไรก็ว่าไปที่รับ Type มาด้วยจะได้ return ถูก รับ Int คืน Int, รับ String คืน String

จบแล้ว เย่! ใช่ครับฟังไม่ผิด Category Theory โดยเนื้อแท้มันมีแค่นี้แหละ แต่มันจะเรื่องที่ละเอียดไปมากกว่านี้อีก ไว้เรามาต่อกันในบล็อกหน้านะครับ ถ้าใครมีข้อสงสัยหรืออะไรยังไงทักมาได้เลยนะครับผม

Top comments (0)