让我们假设我有一个具有两个类型参数的特征,例如
trait Qux[A, B]
Run Code Online (Sandbox Code Playgroud)
和另一个具有更高通道类型参数的特征,例如
trait Turkle[C[_]]
Run Code Online (Sandbox Code Playgroud)
我希望能够将一个固定值替换为其中一个类型参数Qux,以便它可以用于参数化Turkle.
这是一个示例(在Scala中没有意义的代码!):
trait Baz[A] extends Turkle[Qux[A, _]]
Run Code Online (Sandbox Code Playgroud)
任何人有任何想法如何实现这种效果?
考虑io包装中提供的默认编解码器。
implicitly[io.Codec].name //res0: String = UTF-8
Run Code Online (Sandbox Code Playgroud)
它是“低优先级”隐式的,因此很容易覆盖而不会产生歧义。
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
implicitly[io.Codec].name //res1: String = US-ASCII
Run Code Online (Sandbox Code Playgroud)
提高优先级也很容易。
import io.Codec.fallbackSystemCodec
implicit val betterCodec: io.Codec = io.Codec("US-ASCII")
implicitly[io.Codec].name //won't compile: ambiguous implicit values
Run Code Online (Sandbox Code Playgroud)
但是我们可以朝相反的方向前进吗?我们可以创建一个低级别的隐式来禁用(“歧义化”)默认值吗?我一直在研究优先级方程式,并使用低优先级隐式变量进行操作,但尚未创建默认值的歧义。
我正在尝试在 Scala 中实现康威的超现实数字。超现实数是递归定义的——作为一对超现实数的集合,称为左和右,这样右集中的任何元素都不小于或等于左集中的任何元素。这里超现实数之间的关系“小于或等于”也是递归定义的:我们说x ? Ÿ如果
我们首先将零定义为一对空集,然后使用零来定义 1 和 -1,依此类推。
我无法弄清楚如何在编译时强制执行超现实数字的定义。这就是我现在所拥有的:
case class SurrealNumber(left: Set[SurrealNumber], right: Set[SurrealNumber]) {
if ((for { a <- left; b <- right; if b <= a } yield (a, b)).nonEmpty)
throw new Exception
def <=(other: SurrealNumber): Boolean =
!this.left.exists(other <= _) && !other.right.exists(_ <= this)
}
val zero = SurrealNumber(Set.empty, Set.empty)
val one = …Run Code Online (Sandbox Code Playgroud) 我怀疑我有一个根本性的误解需要纠正,所以将从一般概念开始,然后放大导致我这样思考的特定实例。
一般来说,是否可以编写一个类型签名具有参数化类型的函数,并根据类型参数是否属于类型类来采取不同的操作?
例如,如果你有
data MyTree a = Node { val :: a, left :: Maybe (MyTree a), right :: Maybe (MyTree a) }
prettyPrint :: MyTree a -> String
prettyPrint (Show a => ...) t = show (val t)
prettyPrint t = show "?"
Run Code Online (Sandbox Code Playgroud)
哪里prettyPrint $ Node 'x' Nothing Nothing会打印x而prettyPrint $ Node id Nothing Nothing会打印?。
引导我来到这里的是我正在处理复杂的参数化数据类型(例如MyTree)的一些实例,在我需要进行一些调试之前,它进展顺利。当我插入trace语句时,我发现自己希望我的数据类型参数派生显示,当我使用测试(可显示)数据时。但我明白,正如 LYAH 所说的那样,永远不应该在数据声明中添加类型类约束。这是有道理的,我不应该仅仅因为我想调试它就人为地限制我的数据类型。
因此,我最终将类型类约束添加到我正在调试的代码中,但很快发现它们像病毒一样传播。每个调用我正在调试的低级函数的函数也需要添加约束,直到我基本上暂时将约束添加到每个函数,以便我可以获得足够的测试覆盖率。现在我的测试代码正在污染我正在尝试开发的代码并使其偏离轨道。
我认为最好采用模式匹配并将约束排除在签名之外,或者使用多态性并定义函数的调试版本,或者以其他方式将调试跟踪包装在仅在类型参数是实例时才触发的条件中的Show。但在我的徘徊中,我找不到一种方法来做到这一点,也找不到明智的替代方案。
我正在尝试在 dotty 中学习元编程。具体编译时间代码生成。我认为通过构建一些东西来学习是一种很好的方法。所以我决定制作一个 CSV 解析器,它将行解析为案例类。我想使用dotty宏来生成解码器
trait Decoder[T]{
def decode(str:String):Either[ParseError, T]
}
object Decoder {
inline given stringDec as Decoder[String] = new Decoder[String] {
override def decode(str: String): Either[ParseError, String] = Right(str)
}
inline given intDec as Decoder[Int] = new Decoder[Int] {
override def decode(str: String): Either[ParseError, Int] =
str.toIntOption.toRight(ParseError(str, "value is not valid Int"))
}
inline def forType[T]:Decoder[T] = ${make[T]}
def make[T:Type](using qctx: QuoteContext):Expr[Decoder[T]] = ???
}
Run Code Online (Sandbox Code Playgroud)
我已经为Int&提供了基本的解码器String,现在我正在寻找def make[T:Type]方法的指导。如何T在此方法中迭代案例类的参数列表?有没有推荐的方法或模式来做到这一点?
我有以下代码:
source
.mapValues(value -> value + " Stream it!!!")
.print(Printed.toSysOut());
Run Code Online (Sandbox Code Playgroud)
如您所见,mapValues需要一个lambda表达式.
现在,我正在使用Java库,但应用程序是用Scala编写的.如何将Scala lambda传递给Java代码?
我尝试了以下方法:
source
.mapValues(value => value + "hello")
.print(Printed.toSysOut)
Run Code Online (Sandbox Code Playgroud)
但编译器抱怨:
[error] (x$1: org.apache.kafka.streams.kstream.Printed[String,?0(in value x$1)])Unit <and>
[error] (x$1: org.apache.kafka.streams.kstream.KeyValueMapper[_ >: String, _ >: ?0(in value x$1), String])Unit <and>
[error] (x$1: String)Unit
[error] cannot be applied to (org.apache.kafka.streams.kstream.Printed[Nothing,Nothing])
[error] .print(Printed.toSysOut)
[error] ^
[error] two errors found
[error] (compile:compileIncremental) Compilation failed
[error] Total time: 2 s, completed Nov 19, 2017 7:53:44 PM
Run Code Online (Sandbox Code Playgroud) 如何防止在scala代码中使用特定的隐式?
例如,最近我被https://github.com/scala/scala/blob/68bad81726d15d03a843dc476d52cbbaf52fb168/src/library/scala/io/Codec.scala#L76Codec提供的默认值所困扰。有没有办法确保任何调用a的代码都implicit codec: Codec不会使用所提供的代码fallbackSystemCodec?或者,是否可以阻止所有隐式编解码器?
这是应该使用scalafix进行的吗?
这是fs2文档中的一段代码。该函数go是递归的。问题是我们如何知道它是否是堆栈安全的,以及如何推断任何函数是否是堆栈安全的?
import fs2._
// import fs2._
def tk[F[_],O](n: Long): Pipe[F,O,O] = {
def go(s: Stream[F,O], n: Long): Pull[F,O,Unit] = {
s.pull.uncons.flatMap {
case Some((hd,tl)) =>
hd.size match {
case m if m <= n => Pull.output(hd) >> go(tl, n - m)
case m => Pull.output(hd.take(n.toInt)) >> Pull.done
}
case None => Pull.done
}
}
in => go(in,n).stream
}
// tk: [F[_], O](n: Long)fs2.Pipe[F,O,O]
Stream(1,2,3,4).through(tk(2)).toList
// res33: List[Int] = List(1, 2)
Run Code Online (Sandbox Code Playgroud)
如果我们go从另一个方法调用,它也是安全的吗?
def tk[F[_],O](n: …Run Code Online (Sandbox Code Playgroud) 我有一个包含 Scala (2.13.1) 和 Java 文件的 sbt 项目。
\n我想使用 Java 14 编译 java 文件,包括预览功能。
\n我该怎么做?
按照上面的 oracle 文档,我尝试设置 javaOptions + javacOptions:
\njavaOptions ++= Seq("--enable-preview"), // when running\njavacOptions ++= Seq("--enable-preview", "--release", "14"), // when compiling\nRun Code Online (Sandbox Code Playgroud)\n但是当我编译一个使用预览功能的简单 Java 文件时,例如:
\npackage example;\n\npublic record Person(String name, Integer age) {}\nRun Code Online (Sandbox Code Playgroud)\n我得到:
\n\n\n[错误] /Users/dvir/learn/playground/src/main/java/example/Person.java:3:15: 类型声明的非法开始
\n
\n[错误] 公共记录 Person(字符串名称, 整数年龄) {}
\n[错误] ^
注意:\n我在 Mac 上使用AdoptOpenJDK 14。
\n我的JAVA_HOME是/Library/Java/JavaVirtualMachines/adoptopenjdk-14.jdk/Contents/Home.
\n使用时jshell …
https://docs.scala-lang.org/scala3/reference/metaprogramming/compiletime-ops.html上的 Scala 3 参考文献提到了 Scala 3 mataprogramming 可能实现的一些“类似 Prolog 的编程风格”:
到目前为止的问题是,类似于 Prolog 的隐式搜索编程风格变得病毒式传播:一旦某个构造依赖于隐式搜索,它就必须被编写为逻辑程序本身。
但它们都保留了基于逻辑编程的隐式搜索程序的病毒性。
我做了一些搜索,但只知道它在某种程度上滥用了 Scala 编译时行为,并且其中的某些内容类似于 Prolog。
什么是“类似 Prolog 的编程风格”以及它是如何工作的?什么类似于Prolog?它在 Scala 3 中有效吗?