2

更新

这个问题是关于用AnyinA替换的step(x.flatMap((a: Any) => f(a).flatMap(g)))。模式匹配中的类型擦除似乎使这变得困难。

def step[F[_], A](freeFA: Free[F,A]): Free[F,A] =
  freeFA match {
    case FlatMap(
      FlatMap(x, f), g
    ) => step(x.flatMap((a: Any) => f(a).flatMap(g)))
    .
    .
    .

  }

我很欣赏评论中的观点,即 Free monad 与问题的症结无关。我需要的示例包括泛型类型A和泛型类型F[_](更高种类的类型?)。

这是一个迂腐的问题,我很想知道“如何绕过类型擦除”(如何在 Scala 上绕过类型擦除?或者,为什么我不能获得我的集合的类型参数?),即使代码编译。我自己不知道如何将 TypeTags 应用于此。

静态类型检查的提及很有用。有人会解释为什么Any设置为A静态类型检查而不是动态类型检查吗?我相信类型擦除使静态类型检查在这里变得不可能,并且编译器正在退回到动态类型检查以解析AnyA. 谢谢


我有三个案例类,

case class Return[F[_],A](a: A) extends Free[F, A]
case class Suspend[F[_],A](s: F[A]) extends Free[F, A]
case class FlatMap[F[_],A,B](s: Free[F, A],
  f: A => Free[F, B]) extends Free[F, B]

从 trait 继承Free

sealed trait Free[F[_],A] {
  def flatMap[B](f: A => Free[F,B]): Free[F,B] =
    FlatMap(this, f)
  def map[B](f: A => B): Free[F,B] =
    flatMap(f.andThen(Return(_)))
  }

step,以及上面的类,是“Scala 中的函数式编程”第 13 章中用于实现蹦床的练习的一部分。

因为类型擦除不鼓励case FlatMap(FlatMap(x, f), g)Any. 然后,给定的匿名函数的所需签名x.flatMap变为Any=>Free[F,A]。我希望这个函数所需的签名是A=>Free[F,A]——运行时的真正签名。

def step[F[_], A](freeFA: Free[F,A]): Free[F,A] =
  freeFA match {
    case FlatMap(
      FlatMap(x, f), g
    ) => step(x.flatMap((a: Any) => f(a).flatMap(g)))
    .
    .
    .

  }

注释给flatMapas的匿名函数的输入类型A会使编译失败,

step(x.flatMap((a: A) => f(a).flatMap(g)))

我明白这是因为A它只是以下的一个子集Any

 [error]  found   : A => fpinscala.iomonad.IO3.Free[F,A]
 [error]  required: Any => fpinscala.iomonad.IO3.Free[F,A]

Any类型擦除使我无法缩小范围A

def step[F[_], A](freeFA: Free[F,A]): Free[F,A] =
  freeFA match {
    case FlatMap(
      FlatMap(
        x: Free[F,A],
        f: Function1[A,Free[F,A]]
      ),
      g: Function1[A,Free[F,A]]
    ) => step(x.flatMap((a: A) => f(a).flatMap(g)))
   .
   .
   .
  }

以这种方式注释case语句除了文档之外没有其他用途,甚至会导致问题,写在这里:Scala: type annotations make tail recursion check fail

我不知道如何将 TypeTags 应用于这种情况。

我怎样才能注释这个语句来case打倒?谢谢!!AnyA

4

0 回答 0