我正在使用NonEmptyString精炼库中的类型。当连接两个字符串时,至少其中一个非空,结果显然是另一个非空字符串。但是有没有一种方法可以让 Scala 编译器相信这一事实,而不使用诸如 之类的不安全方法NonEmptyString.unsafeFrom?
我正在尝试编写一个宏来简化一些与 monad 相关的代码(我使用cats 1.6.0 作为Monads)。现在我只想能够编写lift[F](a)whereF是一个一元类型的构造函数,并将其扩展为a.pure[F]. 看起来很简单,但我无法让它工作。
现在我有这个代码来帮助类型推断:
object Macros {
class LiftPartiallyApplied[F[_]] {
def apply[A](a: A): F[A] = macro MacroImpl.liftImpl[F, A]
}
def lift[F[_]] = new LiftPartiallyApplied[F]
}
Run Code Online (Sandbox Code Playgroud)
对于宏的实际实现:
object MacroImpl {
def liftImpl[F[_], A](c: blackbox.Context)(a: c.Tree)(implicit tt: c.WeakTypeTag[F[_]]): c.Tree = {
import c.universe._
q"$a.pure[${tt.tpe.typeConstructor}]"
}
}
Run Code Online (Sandbox Code Playgroud)
现在我可以像这样调用宏lift[List](42),它会扩展为42.pure[List],太好了。但是当我用更复杂的类型调用它时,比如lift[({type F[A] = Either[String, A]})#F](42),它会扩展到42.pure[Either],这显然是坏的,因为它Either是一个二进制类型的构造函数而不是一元类型的构造函数。问题是我只是不知道该放什么而不是${tt.tpe.typeConstructor}……
// 编辑:由于人们显然无法重现该问题,因此我制作了一个完整的存储库:https : //github.com/mberndt123/macro-experiment 我现在将尝试找出 Dmytro 和我自己的项目之间的区别是。
假设我们有一个包含 3 个子案例类的特征。当我们将此特征与其中两个匹配而忘记检查第三个时,我们可能在编译时没有注意到它,然后我们会收到运行时错误,尤其是在相互递归函数中使用此模式匹配的情况下。
是否有任何语言构造(可能是某种特定的模式匹配)可以确保处理所有子类?如果是这样,更复杂的模式匹配呢?(比仅仅匹配特征的子类更复杂)是否有任何机制可以让我们确保这些模式匹配是完整的功能?
猫效应有什么作用IO.suspend以及为什么有用?有文档,但并不完全清楚。
该文档给出了以下用例:
import cats.effect.IO
def fib(n: Int, a: Long, b: Long): IO[Long] =
IO.suspend {
if (n > 0)
fib(n - 1, b, a + b)
else
IO.pure(a)
}
Run Code Online (Sandbox Code Playgroud)
举个例子,为什么我要使用上面的函数,而不是下面的类似函数?
import cats.effect.IO
import scala.annotation.tailrec
@tailrec
def fib(n: Int, a: Long, b: Long): IO[Long] =
if (n > 0)
fib(n -1, b, a + b)
else
IO.pure(a)
Run Code Online (Sandbox Code Playgroud)