Scala 3'te özyinelemeli yüksek mertebeden işlev türü

0

Soru

Bir şey yapan ve daha sonra aynı türden başka bir işlev döndüren bir işlev için bir tür tanımlamak istiyorum [kendisi olabilir]. Açık fikir işe yaramadı ("Yasadışı döngüsel tür referansı" hatası):

type Behavior[S] = S => Behavior[S]

Burada eksik olduğum belli bir şey mi var? Ayrıca, "kendini döndüren işlev" fikrini nasıl ifade edeceğimi anlamıyorum.

1

En iyi cevabı

8

Kısa cevap

case class Behavior[S](step: S => Behavior[S])

Uzun cevap (kısa versiyon)

Terminal F-Kömürgebraları oldukça havalı.

Uzun cevap

Uyarı: dikenli tel & co sürü muz falan...

Tamam, öyleyse, bir işlev kavramına sahip olduğunuzu varsayalım F bu, davranışınızın "bir şeyler yapmasının"ne anlama geldiğini yakalar. Çoğu kütüphanede böyle bir şey var:

trait Functor[F[_]]:
  def map[A, B](fa: F[A])(f: A => B): F[B]

Bir F- kömür cebri A aslında sadece bir işlevdir A -e doğru F[A]:

trait FCoalg[F[_]: Functor, A]:
  def apply(a: A): F[A]

Şimdi, bir terminal F- kömür cebri T bu bir F-ek olarak her diğerinden bir özelliğe sahip olan coalgebra F- kömür cebri A aracılık eden bir morfizm var A => T (böylece her şey işe gider, falan filan):

trait TerminalFCoalg[F[_]: Functor, T] extends FCoalg[F, T]:
  def mediate[A](coalg: FCoalg[F, A]): A => T

Keyfi olarak uygulayabilir miyiz F? Anlaşılıyor ki :

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)))

Somut bir örnek uğruna, bu mekanizmanın akla gelebilecek en basit işlev için ne yaptığını görelim Option:

given Functor[Option] with
  def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)

type ConaturalNumber = TerminalFCoalgCarrier[Option]

Terminalin olduğu ortaya çıktı F- coalgebra için Option bunlar sözde doğal sayılardır. Bunlar temel olarak doğal sayılardır, artı sayılabilir sonsuzluktur. Bu şeyler, potansiyel olarak sonsuz "tıklama" işlemlerinin uzunluklarını temsil etmek için oldukça uygundur.

Sonlu bir davranış üzerinde deneyelim:

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)

Şimdi, yukarıdaki makineler bize otomatik olarak bu sayım kelimelerini doğal sayılara çevirmenin evrensel bir yolunu sunuyor. Doğal sayıları tanımlamak için yardımcı bir yöntem ekleyelim (yaklaşık olarak):

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")

Galce kelimeleri saymak için ne gösteriyor?


@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

Tamam, bu çok düzgün. Kendisinin ardılı olan tek bir durumla sonsuz bir tıklama işlemini deneyelim:

object LoopForever extends FCoalg[Option, Unit]:
  def apply(u: Unit) = Some(())

val loopForeverMediatingMorphism =
  summon[TerminalFCoalg[Option, TerminalFCoalgCarrier[Option]]]
    .mediate(LoopForever)

Şimdi tek devleti nasıl tarif ederdi ()?

println(s"${()} -> ${describe(loopForeverMediatingMorphism(()))}")
// () -> probably infinite

İş gibi görünüyor.


Tam kod:

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(()))}")

2021-11-23 21:59:52

Diğer dillerde

Bu sayfa diğer dillerde

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................