我正在尝试编写一些 Scala 代码以实现mtl 风格的自定义行为。例如,为了公开对特定效果进行抽象的“写入数据库”功能,我编写了自己的类型类:
trait CanPersist[M[_]]:
def persistToDB[A](a: A): M[Unit]
given CanPersist[IO] with
def persistToDB[A](a: A): IO[Unit] = IO(???) // Write to DB
Run Code Online (Sandbox Code Playgroud)
IO 实例可以轻松实现,但我感兴趣的是自动为任何基于 IO 的 monad 堆栈提供实例:
// If a Transformer wraps a Monad that can persist then it can persist too
given persistTA[M[_]: CanPersist: Monad, T[_[_], _]: MonadTransformer]:
CanPersist[[A] =>> T[M, A]] with
def persistToDB[A](a: A): T[M, Unit] =
summon[MonadTransformer[T]].lift(summon[CanPersist[M]].persistToDB(a))
Run Code Online (Sandbox Code Playgroud)
问题显然是 cats 没有定义自己的MonadTransformer类型类;幸运的是,自己编写非常简单:
trait MonadTransformer[T[_[_], _]]:
def lift[M[_]: Monad, A](ma: M[A]): T[M, A] …Run Code Online (Sandbox Code Playgroud) functional-programming scala monad-transformers scala-cats given
目前正在学习 Scala 3 隐式,但我很难理解 \xe2\x80\x8bas和with关键字在如下定义中的作用:
given listOrdering[A](using ord: Ordering[A]) as Ordering[List[A]] with\n \xe2\x80\x8bdef compare(a: List[A], b: List[A]) = ...\nRun Code Online (Sandbox Code Playgroud)\n我尝试谷歌搜索,但没有找到任何好的解释。我已经检查了 Scala 3 参考指南,但我发现的唯一一件事as是它是一个“软修饰符”,但这并不能真正帮助我理解它的作用......我猜as在上面的代码以某种方式用于澄清这listOrdering[A]是一个Ordering[List[A]](就像正在进行某种类型的打字或类型转换?),但如果能找到它背后的真正含义那就太好了。
至于with,我只在 Scala 2 中使用它来继承多个特征(class A extends B with C with D),但在上面的代码中,它似乎以不同的方式使用......
非常感谢任何解释或为我指明查看文档的正确方向!
\n另外,如果用 Scala 2 编写上面的代码会是什么样子?也许这可以帮助我弄清楚发生了什么事......
\n假设我有一些类型类
trait FooBar[X]
Run Code Online (Sandbox Code Playgroud)
和一个实例FooBar[Int]:
given intIsFooBar: FooBar[Int] = new FooBar {}
Run Code Online (Sandbox Code Playgroud)
现在,假设我有一个Intf具有某种成员类型的接口A,并且还保证有一个given FooBar[A]:
trait Intf:
type A
given aIsFoobar: FooBar[A]
Run Code Online (Sandbox Code Playgroud)
现在,我有了类型Int,也有一个FooBar[Int],但是我如何实际实现这个接口呢Int?
如果我尝试
class IntImpl() extends Intf:
type A = Int
given aIsFoobar: FooBar[A] = summon
Run Code Online (Sandbox Code Playgroud)
然后我收到“函数体 IntImpl.aIsFoobar 中的无限循环”错误,因为summon似乎看到的是aIsFoobar而不是intIsFooBar。
如果我尝试使用summon某些辅助辅助变量中的实例,如下所示:
class IntImpl() extends Intf:
type A = Int
private final val _aIsFoobar: FooBar[A] = summon
given aIsFoobar: …Run Code Online (Sandbox Code Playgroud) 我一直在尝试制作一个相对较大的 Perl 程序,多年来它在 CentOS 上运行得非常好,但现在却可以在 Ubuntu 上运行,但这已经成为一个巨大的噩梦。CentOS 使用为 x86_64-linux-thread-multi 构建的 Perl,Ubuntu 使用 x86_64-linux-gnu-thread-multi 构建。AFAIK,当程序调用相同的先前版本时,解释器行为在两种环境中应该相同v5.10.1。然而,我得到了非常不同的行为,包括关于given/when和smartmatch正在进行实验的警告,最重要的是,一系列难以追踪和解决的令人讨厌的错误。given当下面所示的语句(表 1)匹配并调用函数时,会出现一个特定问题。$ailtype然后突然间,从未被触及的switch 变量(称为 )的值从内存中删除了!如果我简单地调用该函数,就不会发生任何令人讨厌的事情。因此,我用语句(表格 2)替换了given/when用法,我的问题是为什么问题仍然出现?!真正避免该问题的唯一形式是简单的/链(形式 3),这清楚地表明问题出在形式 1 和 2 以及 perl 解释器不一致且充满错误的情况下:它甚至不产生“表 2 的实验性警告。forifelsif
这是表格 1(原件):
print "ailtype is $ailtype \n"; # prints "ailtype is 8"
given ($ailtype) {
when (4) { &parse_mascot}
when (5) { &parse_sequest}
when (8) { &parse_spectrast($ms2_results, $rttemp)}
when (9) { &parse_cnstab($ms2_results, …Run Code Online (Sandbox Code Playgroud) 设T1, T2, T3三种类型。我们还定义了该类的两个给定实例Conversion,以便编译器可以从T1toT2和从T2to进行转换T3。
下面的代码可以正常编译:
type T1
type T2
type T3
given Conversion[T1, T2] with
override def apply(x: T1): T2 = ???
given Conversion[T2, T3] with
override def apply(x: T2): T3 = ???
val t1: T1 = ???
val t2: T2 = t1
val t3: T3 = t2
Run Code Online (Sandbox Code Playgroud)
但是当我们尝试从T1到 时会发生什么T3?编译器不会让我们:
val t3: T3 = t1
^^
Found: (t1: T1)
Required: T3
Run Code Online (Sandbox Code Playgroud)
我的问题:编译器无法本机(参见解决方法)链转换是否有特定原因?
我的解决方法 …