簡體   English   中英

如何為 function 類型定義 Monad?

[英]How to define a Monad for a function type?

我是第一次嘗試 Cats,我正在使用 Scala 3,但是我正在嘗試實現一組用於自我教學的解析器組合器; 我停留在 Monad 的tailRecM function 的定義上。 我已經很好地管理了 Functor 和 Applicative。

我已將我的相關類型定義為 function,這樣:

type Parser[A] = (input: List[Token]) => ParseResult[A]

相應的返回類型為:

type ParseResult[A] = Success[A] | Failure 
case class Success[A](value: A, tokens: List[Token])
case class Failure(msg: String, tokens: List[Token])

我目前對tailRecM的定義如下:

@annotation.tailrec
def tailRecM[A, B](init: A)(fn: A => Parser[Either[A, B]]): Parser[B] =
  (input: List[Token]) => 
    fn(init)(input) match {
      case f: Failure => f
      case s: Success[Either[A, B]] => s.value match {
        case Right(b) => Success(b, s.tokens)
        case Left(a) => tailRecM(a)(fn) // won't compile 
      }
  }

如果我嘗試構建,我會得到"Found: Parsing.Parser[B] Required: Parsing.ParseResult[B]" for tailRecM(a)(fn)

據我所知,這個問題源於我的問題Parser[A]類型是 function 類型而不僅僅是值類型這一事實? 我試圖通過修改對tailRecM(a)(fn)(input)tailRecM遞歸調用來改善這個問題,但這顯然不是堆棧安全的,也不會編譯。

我如何解決這個問題,更廣泛地說,我如何為 function 類型實現 Monad 類型類?

使tailRecM本身成為尾遞歸是不可能的; 您需要定義一個尾遞歸輔助方法

以下是cats庫如何為Function1實現tailRecM

  def tailRecM[A, B](a: A)(fn: A => T1 => Either[A, B]): T1 => B =
    (t: T1) => {
      @tailrec
      def step(thisA: A): B =
        fn(thisA)(t) match {
          case Right(b)    => b
          case Left(nextA) => step(nextA)
        }
      step(a)
    }

這是因為單子遞歸是相互尾遞歸的一種形式,其中兩個方法來回調用彼此。 scala 編譯器無法對其進行優化。 因此,我們內聯 monadic 部分的定義,而不是調用flatMap或其他方法

您需要再次將input傳遞給tailRecM調用

tailRecM(a)(fn)(input)

因為tailRecM(a)(fn)返回一個Parser ,但是您需要從返回的ParserParserResult ,就像您在所有其他情況下所做的那樣。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM