如何为函数类型定义单子?
我正在第一次尝试猫,并且正在使用Scala 3,但是我正在尝试实施一组解析器组合者以自行自同学。我被关注tailRecm
单元的函数的定义。我已经管理函数和应用程序。
我将所讨论的类型定义为一个函数:
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
}
}
如果我尝试构建,我会得到“找到:解析。需要:parsing.parseresult [b]“
for tailRecm(a)(fn)
我可以说的是,我的类型<我的类型<, 代码>解析器[A] 是函数类型,而不仅仅是值类型?我试图通过修改tailRecm
递归调用tailRecm(a)(fn)(input)(输入)
来改善问题,但显然这也不是安全的,并且也不会安全,并且也不会安全。编译。
我该如何解决这个问题,更广泛地解决一般的功能类型的单调类型?
I am trying Cats for the first time and am using Scala 3, and I am trying to implement a set of parser combinators for self-pedagogy, however; I am stuck on the definition of the tailRecM
function for Monad. I have managed Functor and Applicative just fine.
I have defined my type in question as a function such that:
type Parser[A] = (input: List[Token]) => ParseResult[A]
with corresponding return types as:
type ParseResult[A] = Success[A] | Failure
case class Success[A](value: A, tokens: List[Token])
case class Failure(msg: String, tokens: List[Token])
My current definition of tailRecM
is as follows:
@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
}
}
If I attempt to build I get "Found: Parsing.Parser[B] Required: Parsing.ParseResult[B]"
for tailRecM(a)(fn)
The issue as far as I can tell stems from the fact that my type in question Parser[A]
is a function type and not simply a value type? I attempted to ameliorate the issue by modifying the tailRecM
recursive call to tailRecM(a)(fn)(input)
but then this is obviously not stack safe, and also will not compile.
How can I resolve this issue, and more broadly, how can I implement the Monad typeclass for function types in general?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
不可能使
tailRecm
本身本身进行尾声;您需要定义一个尾部回复辅助方法,这是
cats
library实现tailRecm
的function> function1
这是因为monadic递归是< em>相互访问,其中两种方法互相呼唤。 Scala编译器无法优化。因此,我们将其嵌入式元素定义,而不是调用
flatmap
或其他方法It's not possible to make
tailRecM
itself tail-recursive; you need to define a tail-recursive helper methodHere's how the
cats
library implementstailRecM
forFunction1
This is because monadic recursion is a form of mutual tail-recursion, where two methods flip back and forth calling each other. The scala compiler can't optimize that. So instead we inline the definition of the monadic part rather than calling
flatMap
or another method您需要再次将
输入
再次传递到tailRecm
呼叫,因为
tailRecm(a)(fn)(fn)
返回parser
,但是您需要从该返回的Parser
中的parserresult
,就像您在所有其他情况下一样。You need to pass the
input
again to thetailRecM
callbecause
tailRecM(a)(fn)
returns aParser
, but you need theParserResult
from that returnedParser
, as you already did in all other cases.