ส่วนขยายฟรีของ monad และปฏิกิริยามีความสัมพันธ์อย่างไร


14

ฉันมาจากพื้นหลัง C # ที่ LINQ พัฒนาเป็น Rx.NET แต่มีความสนใจใน FP เสมอ หลังจากที่ได้รู้จักกับ monads และบางโครงการใน F # ฉันก็พร้อมที่จะลองและก้าวไปอีกระดับ

ตอนนี้หลังจากพูดคุยเกี่ยวกับ monad ฟรีจากผู้คนจาก Scala และการเขียนหลายครั้งใน Haskell หรือ F # ฉันได้พบไวยากรณ์พร้อมล่ามเพื่อความเข้าใจที่คล้ายกับIObservableโซ่

ใน FRP คุณเขียนคำจำกัดความการดำเนินการจากชิ้นส่วนเฉพาะของโดเมนที่เล็กลงรวมถึงผลข้างเคียงและความล้มเหลวที่อยู่ในห่วงโซ่ ใน monad ฟรีถ้าฉันเข้าใจอย่างถูกต้องคุณทำเช่นเดียวกันโดยทำให้การทำงานของคุณเป็น functors และยกพวกเขาโดยใช้ coyoneda

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


2
ต่อไปนี้เป็นวิธีที่น่าสนใจในการคิดเกี่ยวกับปัญหา ... FRP สามารถถูกมองว่าเป็น monad แม้ว่ามันจะไม่ใช่สูตรแบบปกติก็ตาม ส่วนใหญ่ ( แต่ไม่ทั้งหมด) monads เป็นisomorphic กับ monad เช่นเดียวContกับที่ฉันเห็น monad แนะนำว่าไม่สามารถแสดงออกผ่าน monad ได้ฟรีใคร ๆ ก็คงคิดว่า FRP นั้นเป็นได้ ที่สามารถเกือบทุกอย่างอื่น
จูลส์

2
ตาม Erik Meijer ผู้ออกแบบทั้ง LINQ และ Rx.NET IObservableเป็นตัวอย่างของ monad ต่อเนื่อง
Jörg W Mittag

1
ตอนนี้ฉันไม่มีเวลาทำรายละเอียด แต่ฉันเดาว่าทั้งส่วนขยายของ RX และวิธี monad ฟรีบรรลุเป้าหมายที่คล้ายกันมากแต่อาจมีโครงสร้างที่แตกต่างกันเล็กน้อย อาจเป็นไปได้ว่า RX Observables นั้นเป็น monads ด้วยตนเองและจากนั้นคุณสามารถแมปการคำนวณ monad ฟรีโดยใช้สิ่งที่สังเกตได้นั่นคือคร่าวๆว่า "free" ใน "free monad" หมายถึงอะไร หรืออาจจะเป็นความสัมพันธ์ที่ไม่ตรงและคุณเพียงแค่เลือกวิธีที่พวกเขาใช้เพื่อวัตถุประสงค์ที่คล้ายกัน
Tikhon Jelvis

คำตอบ:


6

monads

monadประกอบด้วย

  • endofunctor ในโลกวิศวกรรมซอฟต์แวร์ของเราเราสามารถพูดได้ว่าสิ่งนี้สอดคล้องกับประเภทข้อมูลที่มีพารามิเตอร์ประเภทเดียวที่ไม่ จำกัด ใน C # นี่จะเป็นรูปแบบ:

    class M<T> { ... }
    
  • การดำเนินการที่กำหนดไว้สองประเภทข้อมูลนั้น:

    • return/ pureใช้ค่า "บริสุทธิ์" (เช่นTค่า) และ "ล้อม" ลงใน monad (กล่าวคือสร้างM<T>ค่า) เนื่องจากreturnเป็นคำหลักที่สงวนไว้ใน C # ฉันจะใช้pureเพื่ออ้างอิงการดำเนินการนี้นับจากนี้เป็นต้นไป ใน C # pureจะเป็นวิธีที่มีลายเซ็นเช่น:

      M<T> pure(T v);
      
    • bind/ flatmapใช้เวลาคุ้มค่าเอก ( M<A>) fและฟังก์ชั่น fรับค่า pure และส่งคืนค่า monadic ( M<B>) จากสิ่งเหล่านี้bindสร้างค่า monadic ใหม่ ( M<B>) bindมีลายเซ็น C # ต่อไปนี้:

      M<B> bind(M<A> mv, Func<A, M<B>> f);
      

นอกจากนี้ยังจะเป็น monad pureและbindจะต้องปฏิบัติตามกฎหมายทั้งสาม monad

ตอนนี้วิธีหนึ่งในการสร้างแบบจำลอง monads ใน C # คือการสร้างส่วนต่อประสาน:

interface Monad<M> {
  M<T> pure(T v);
  M<B> bind(M<A> mv, Func<A, M<B>> f);
}

(หมายเหตุ: เพื่อให้สิ่งต่าง ๆ สั้นและแสดงออกฉันจะเอาเสรีภาพพร้อมรหัสในคำตอบนี้)

ตอนนี้เราสามารถสร้าง monads สำหรับ datagypes ที่เป็นรูปธรรมMonad<M>ได้ ตัวอย่างเช่นเราอาจใช้ monad ต่อไปนี้เพื่อIEnumerable:

class IEnumerableM implements Monad<IEnumerable> {
  IEnumerable<T> pure(T v) {
    return (new List<T>(){v}).AsReadOnly();
  }

  IEnumerable<B> bind(IEnumerable<A> mv, Func<A, IEnumerable<B>> f) {
    ;; equivalent to mv.SelectMany(f)
    return (from a in mv
            from b in f(a)
            select b);
  }
}

(ฉันตั้งใจใช้ไวยากรณ์ LINQ ในการเรียกความสัมพันธ์ระหว่างไวยากรณ์ LINQ และ monads แต่โปรดทราบว่าเราสามารถแทนที่แบบสอบถาม LINQ ด้วยการเรียกไปยังSelectMany)

ตอนนี้เราสามารถกำหนด monad ให้IObservableหรือไม่ ดูเหมือนว่าจะเป็นเช่นนั้น:

class IObservableM implements Monad<IObservable> {
  IObservable<T> pure(T v){
    Observable.Return(v);
  }

  IObservable<B> bind(IObservable<A> mv, Func<A, IObservable<B>> f){
    mv.SelectMany(f);
  }
}

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

ฟรี Monads

ไม่มีเอกพจน์ "ฟรี monad" แต่พระฟรีเป็นชั้นของพระที่สร้างขึ้นจาก functors นั่นคือเมื่อได้รับ functor Fเราสามารถรับ monad สำหรับF(เช่น monad ฟรีของF) โดยอัตโนมัติ

functors

เช่นเดียวกับ monads ฟังก์ชั่นสามารถกำหนดโดยสามรายการต่อไปนี้:

  • ประเภทข้อมูลพารามิเตอร์กว่าตัวแปรชนิดเดียวที่ไม่ จำกัด
  • สองการดำเนินงาน:

    • pureห่อค่าที่บริสุทธิ์เข้าไปใน functor นี่คล้ายกับpureสำหรับ monad ในความเป็นจริงสำหรับ functors ที่เป็น monads ทั้งสองควรเหมือนกัน
    • fmapจับคู่ค่าในอินพุตกับค่าใหม่ในเอาต์พุตผ่านฟังก์ชันที่กำหนด มันคือลายเซ็น:

      F<B> fmap(Func<A, B> f, F<A> fv)
      

เช่นเดียวกับ monads หน้าที่ต้องปฏิบัติตามกฎหมายของ functor

คล้ายกับ monads เราสามารถจำลอง functionors ผ่านทางอินเตอร์เฟสต่อไปนี้:

interface Functor<F> {
  F<T> pure(T v);
  F<B> fmap(Func<A, B> f, F<A> fv);
}

ตอนนี้เนื่องจาก monads เป็น sub-class ของ functors เราสามารถ refactor ได้Monadอีกเล็กน้อย:

interface Monad<M> extends Functor<M> {
  M<T> join(M<M<T>> mmv) {
    Func<T, T> identity = (x => x);
    return mmv.bind(x => x); // identity function
  }

  M<B> bind(M<A> mv, Func<A, M<B>> f) {
    join(fmap(f, mv));
  }
}

นี่ฉันได้เพิ่มวิธีการเพิ่มเติมjoinและให้การใช้งานเริ่มต้นของทั้งสองและjoin bindอย่างไรก็ตามโปรดทราบว่าสิ่งเหล่านี้เป็นคำจำกัดความแบบวงกลม ดังนั้นคุณต้องแทนที่อย่างน้อยหนึ่งรายการ นอกจากนี้ทราบว่าจะรับมาในขณะนี้จากpureFunctor

IObservable และ Monads ฟรี

ตอนนี้ตั้งแต่เราได้กำหนดไว้สำหรับ monad IObservableและตั้งแต่ monads เป็นชั้นย่อยของ functors มันตามที่เราจะต้องสามารถที่จะกำหนดเช่น functor IObservableสำหรับ นี่คือนิยามเดียว:

class IObservableF implements Functor<IObservable> {
  IObservable<T> pure(T v) {
    return Observable.Return(v);
  }

  IObservable<B> fmap(Func<A, B> f, IObservable<A> fv){
    return fv.Select(f);
  }
}

ตอนนี้เราได้กำหนด functor ไว้IObservableแล้วเราสามารถสร้าง monad ฟรีจาก functor นั้นได้ และนั่นคือวิธีการที่IObservableเกี่ยวข้องกับ monads ฟรี - คือว่าเราสามารถสร้าง monad IObservableฟรีจาก


ความเข้าใจที่ลึกซึ้งของทฤษฎีหมวดหมู่! ฉันเป็นบางสิ่งที่ไม่ได้พูดถึงว่ามันถูกสร้างขึ้นอย่างไรเกี่ยวกับความแตกต่างเมื่อสร้างสถาปัตยกรรมเชิงหน้าที่และองค์ประกอบของเอฟเฟกต์แบบจำลองกับพวกเขา FreeMonad สามารถใช้ในการสร้าง DSL สำหรับการดำเนินการ reified ในขณะที่ IObservables เพิ่มเติมเกี่ยวกับค่าที่ไม่ต่อเนื่องในช่วงเวลา
MLProgrammer-CiM

1
@ MLProgrammer-CiM ฉันจะดูว่าฉันสามารถเพิ่มข้อมูลเชิงลึกเกี่ยวกับเรื่องนั้นในอีกไม่กี่วันข้างหน้า
Nathan Davis

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