คำตอบสั้น
case class Behavior[S](step: S => Behavior[S])
นานคำตอบ(สั้นๆ)
เทอร์มินัล F-Coalgebras เป็นค่อนข้างเจ๋งนะ
นานคำตอบ
คำเตือน:ลายของรั้วลวดหนามสาย&เพื่อนร่วมกล้วยหรืออะไรบางอย่าง...
โอเคงั้นคิดว่าคุณมีคอนเซ็ปต์ของ functor F
ที่จับภาพอะไรมันหมายถึงพฤติกรรมของเธอ"มีอะไร". ในที่สุดไลบรารีนคือเรื่องแบบนี้:
trait Functor[F[_]]:
def map[A, B](fa: F[A])(f: A => B): F[B]
เป็ F
-coalgebra A
เป็นสิ่งจำเป็นอันเที่ยงแค่ฟังก์ชันจาก A
ต้อง F[A]
:
trait FCoalg[F[_]: Functor, A]:
def apply(a: A): F[A]
ตอนนี้ เทอร์มินัล F
-coalgebra T
เป็ F
-coalgebra ยิ่งไปกว่านั้นซึ่งมีคุณสมบัติจากคนอื่นทุกคน F
-coalgebra A
มี mediating morphism A => T
(เช่นนั้นทุกอย่าง commutes,ห่ห่):
trait TerminalFCoalg[F[_]: Functor, T] extends FCoalg[F, T]:
def mediate[A](coalg: FCoalg[F, A]): A => T
เราสามารถดำเนินมันสำหรับด็จการ F
? มันกลายเป็นว่าเราสามารถ:
case class TerminalFCoalgCarrier[F[_]: Functor](
step: () => F[TerminalFCoalgCarrier[F]]
)
given tfcImpl[F[_]: Functor]: TerminalFCoalg[F, TerminalFCoalgCarrier[F]] with
def apply(a: TerminalFCoalgCarrier[F]): F[TerminalFCoalgCarrier[F]] = a.step()
def mediate[A](coalg: FCoalg[F, A]): A => TerminalFCoalgCarrier[F] = a =>
TerminalFCoalgCarrier(() => summon[Functor[F]].map(coalg(a))(mediate(coalg)))
สำหรับผลประโยชน์ของคอนกรีตตัวอย่างให้เห็นว่ามัน contraption มันสำหรับงานง่ายสุด imaginable functor Option
:
given Functor[Option] with
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
type ConaturalNumber = TerminalFCoalgCarrier[Option]
มันกลายเป็นว่าเทอร์มินัล F
-coalgebra สำหรับ Option
ที่เรียกว่า conatural ตัวเลข. นี่เป็นเป็นธรรมชาติของตัวเลขบวกกับ countable แม้สถานการณ์จะเปลี่ยนไป. เรื่องพวกนี้เป็นดีๆมที่เหมาะสมสำหรับเป็นตัวแทนให้เดินทางมาไกลของเป็นไปได้ว่าถึงไม่มีที่สิ้นสุดคือ..."การคลิก"โพรเซส.
ปล่อยให้ลองมันเป็น finite พฤติกรรม:
enum WelshCounting:
case Eeny
case Meeny
case Miny
case Moe
object WelshCountingOptionCoalg extends FCoalg[Option, WelshCounting]:
def apply(w: WelshCounting): Option[WelshCounting] =
import WelshCounting._
w match
case Eeny => None
case Meeny => Some(Eeny)
case Miny => Some(Meeny)
case Moe => Some(Miny)
val welshMediatingMorphism =
summon[TerminalFCoalg[Option, TerminalFCoalgCarrier[Option]]]
.mediate(WelshCountingOptionCoalg)
ตอนนี้ที่ด้านบน machinery โดยอัตโนมัติให้เป็นรูปแบบสากลที่จะแปลพวกนั้นนับคำเข้าไปใน conatural นตัวเลข ปล่อยให้เป็นการเพิ่มผู้ช่วยวิธีการเพื่อธิบาย conatural ตัวเลข(ประมาณ):
def describe(c: ConaturalNumber): String =
var counter = 0
var curr = c
while true do
curr.step() match
case None => return s"${counter}"
case Some(next) =>
if counter > 42 then
return "probably infinite"
else {
counter += 1
curr = next
}
throw new Error("We have counted to infinity, yay! :D")
มันแสดงสำหรับภาษาเวลช์ name หวังจะพูดมันออกมายังไง
@main def demo(): Unit =
for w <- WelshCounting.values do
val conat = welshMediatingMorphism(w)
println(s"${w} -> ${describe(conat)}")
// Eeny -> 0
// Meeny -> 1
// Miny -> 2
// Moe -> 3
โอเคนั่นเป็นคนเรียบร้อย ลองคำถาม infinitely การคลิกระบวนการกับแค่หนึ่งของรัฐนั้นคือผู้สืบทอดของตัวเอง:
object LoopForever extends FCoalg[Option, Unit]:
def apply(u: Unit) = Some(())
val loopForeverMediatingMorphism =
summon[TerminalFCoalg[Option, TerminalFCoalgCarrier[Option]]]
.mediate(LoopForever)
ยังไงมันอธิบายเดียวของรัฐ ()
?
println(s"${()} -> ${describe(loopForeverMediatingMorphism(()))}")
// () -> probably infinite
ดูเหมือนไปทำงานแล้ว
เต็มไปด้วยรหัส:
trait Functor[F[_]]:
def map[A, B](fa: F[A])(f: A => B): F[B]
trait FCoalg[F[_]: Functor, A]:
def apply(a: A): F[A]
trait TerminalFCoalg[F[_]: Functor, T] extends FCoalg[F, T]:
def mediate[A](coalg: FCoalg[F, A]): A => T
case class TerminalFCoalgCarrier[F[_]: Functor](
step: () => F[TerminalFCoalgCarrier[F]]
)
given tfcImpl[F[_]: Functor]: TerminalFCoalg[F, TerminalFCoalgCarrier[F]] with
def apply(a: TerminalFCoalgCarrier[F]): F[TerminalFCoalgCarrier[F]] = a.step()
def mediate[A](coalg: FCoalg[F, A]): A => TerminalFCoalgCarrier[F] = a =>
TerminalFCoalgCarrier(() => summon[Functor[F]].map(coalg(a))(mediate(coalg)))
given Functor[Option] with
def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
type ConaturalNumber = TerminalFCoalgCarrier[Option]
def describe(c: ConaturalNumber): String =
var counter = 0
var curr = c
while true do
curr.step() match
case None => return s"${counter}"
case Some(next) =>
if counter > 42 then
return "probably infinite"
else {
counter += 1
curr = next
}
throw new Error("We cannot count to infinity :(")
enum WelshCounting:
case Eeny
case Meeny
case Miny
case Moe
object WelshCountingOptionCoalg extends FCoalg[Option, WelshCounting]:
def apply(w: WelshCounting): Option[WelshCounting] =
import WelshCounting._
w match
case Eeny => None
case Meeny => Some(Eeny)
case Miny => Some(Meeny)
case Moe => Some(Miny)
val welshMediatingMorphism =
summon[TerminalFCoalg[Option, TerminalFCoalgCarrier[Option]]]
.mediate(WelshCountingOptionCoalg)
object LoopForever extends FCoalg[Option, Unit]:
def apply(u: Unit) = Some(())
val loopForeverMediatingMorphism =
summon[TerminalFCoalg[Option, TerminalFCoalgCarrier[Option]]]
.mediate(LoopForever)
@main def demo(): Unit =
for w <- WelshCounting.values do
val conat = welshMediatingMorphism(w)
println(s"${w} -> ${describe(conat)}")
println(s"${()} -> ${describe(loopForeverMediatingMorphism(()))}")