我想為一個函式定義一個型別,該函式執行某些操作然后回傳另一個相同型別的函式[可以是它自己]。顯而易見的想法不起作用(“非法回圈型別參考”錯誤):
type Behavior[S] = S => Behavior[S]
有什么明顯的東西我在這里失蹤了嗎?我也不明白如何表達“函式回傳自身”的想法。
uj5u.com熱心網友回復:
簡答
case class Behavior[S](step: S => Behavior[S])
長答案(短版)
終端 F-Coalgebras非常酷。
長答案
警告:很多帶刺鐵絲網和香蕉,或其他東西......
好的,那么,假設您有一個函子的概念,F它可以捕獲您的行為“做某事”的含義。在大多數庫中是這樣的:
trait Functor[F[_]]:
def map[A, B](fa: F[A])(f: A => B): F[B]
一個F-coalgebraA本質上只是一個函式 from Ato F[A]:
trait FCoalg[F[_]: Functor, A]:
def apply(a: A): F[A]
現在,終端 F-coalgebraT是一個F-coalgebra,它另外有一個屬性,即從所有其他F-coalgebraA有一個中介態射A => T(這樣一切都可以交換,等等):
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)))
為了一個具體的例子,讓我們看看這個裝置對最簡單的可以想象的函子做了什么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 forOption是所謂的共自然數。這些基本上是自然數,加上可數無窮大。這些東西非常適合表示潛在無限“點擊”程序的長度。
讓我們在有限行為上嘗試一下:
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)
現在,上述機制自動為我們提供了一種通用方法將這些計數詞轉換為共自然數。讓我們添加一個輔助方法來描述共自然數(大約):
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")
威爾士數詞顯示什么?
@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
好的,這很整潔。讓我們嘗試一個無限點擊程序,只有一個狀態是它自己的后繼狀態:
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(()))}")
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/366269.html
上一篇:TypeClasse實作最佳語法
下一篇:scala:用于理解Option
