更新
这个问题是关于用Any
inA
替换的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
静态类型检查而不是动态类型检查吗?我相信类型擦除使静态类型检查在这里变得不可能,并且编译器正在退回到动态类型检查以解析Any
为A
. 谢谢
我有三个案例类,
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)))
.
.
.
}
注释给flatMap
as的匿名函数的输入类型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
打倒?谢谢!!Any
A