作为JI的初学者,我常常遇到隐性程序,与更熟悉的显式形式相比,它们看起来相当拜占庭.
现在只是因为我发现解释困难并不意味着默会形式是错误的或错误的.通常,默认形式比显式形式短得多,因此更容易在视觉上同时看到所有形式.
专家提问:这些隐性形式是否表达了更好的结构感,并可能提炼出潜在的计算机制?还有其他好处吗?
我希望答案是肯定的,对于一些非平凡的例子也是如此......
在下面的例子中,有没有办法避免隐式分辨率选择defaultInstance并使用intInstance而不是?代码后的更多背景:
// the following part is an external fixed API
trait TypeCls[A] {
def foo: String
}
object TypeCls {
def foo[A](implicit x: TypeCls[A]) = x.foo
implicit def defaultInstance[A]: TypeCls[A] = new TypeCls[A] {
def foo = "default"
}
implicit val intInstance: TypeCls[Int] = new TypeCls[Int] {
def foo = "integer"
}
}
trait FooM {
type A
def foo: String = implicitly[TypeCls[A]].foo
}
// end of external fixed API
class FooP[A:TypeCls] { // with type …Run Code Online (Sandbox Code Playgroud) 使用《Swift 语言指南:扩展》中的示例代码我已经像这样扩展了 struct Double
extension Double {
func someFunc() {
print("someFunc")
}
}
Run Code Online (Sandbox Code Playgroud)
我很惊讶这个声明
2.someFunc()
Run Code Online (Sandbox Code Playgroud)
没有生成编译时错误,例如:“Int”类型的值没有成员“someFunc”。我预计 2 的值会隐式转换为 Int,但 Swift 将其转换为 Double。这是为什么 ?Swift 如何确定本例中 2 的值是 Double 类型?
然后我尝试像这样调用 someFunc()
let x = 2
x.someFunc()
Run Code Online (Sandbox Code Playgroud)
这里我得到了预期的编译时错误
这是否与Swift 编程语言 3.0.1:语言指南:基础知识:类型安全和类型推断中的陈述相矛盾?
类型推断使编译器能够在编译代码时自动推断出特定表达式的类型,只需检查您提供的值即可。
编辑
从响应中我了解到发生这种情况是因为 Double 符合 ExpressibleByIntegerLiteral 协议。然而 Float 结构也确实符合它以及其他一些类型。下面我创建了也符合该协议的结构。然而最终在编译时选择了 Double。为什么?一个扩展的方法相对于其他扩展的方法的优先级是如何确定的?
struct someStruct: ExpressibleByIntegerLiteral{
var i:Int = 0
init(integerLiteral value: Int64){
i = Int(value)
}
}
extension someStruct {
func someFunc() {print("Somestruct someFunc") }
}
extension Double { …Run Code Online (Sandbox Code Playgroud) 简短问题:
有没有办法让scala编译器告诉我程序中给定点使用的某个隐式声明在哪里?
如果没有,是否可以手动遵循一种算法来找出隐式声明的位置?
长问题:
我正在遵循简单的Spray Crud 教程。
在下面的代码片段中(作为教程的此仓库):
pathEnd {
post {
entity(as[Question]) { question =>
completeWithLocationHeader(
resourceId = questionService.createQuestion(question),
ifDefinedStatus = 201, ifEmptyStatus = 409)
}
}
} ~
Run Code Online (Sandbox Code Playgroud)
as接受一个隐式类型FromRequestUnmarshaller[T](此处为完整资料):
def as[T](implicit um: FromRequestUnmarshaller[T]) = um
Run Code Online (Sandbox Code Playgroud)
当我问IntelliJ时,这个隐式是从哪里来的(使用CMD + SHIFT + P),我得到:
当我遵循第一个提示时,我得到了:
trait UnmarshallerLifting {
implicit def fromRequestUnmarshaller[T](implicit um: FromMessageUnmarshaller[T]): FromRequestUnmarshaller[T] =
new FromRequestUnmarshaller[T] {
def apply(request: HttpRequest): Deserialized[T] = um(request)
}
...
Run Code Online (Sandbox Code Playgroud)
这并不能帮助我确定隐式FromRequestUnmarshaller[T]函数的来源,因为如果我检查类层次结构,就无法确定特征是如何UnmarshallerLifting混合的QuestionResource …
我有一个计算数字类型的平方和的函数,如下所示。
import cats.syntax.functor._
import cats.syntax.applicative._
import cats.{Id, Monad}
import scala.language.higherKinds
object PowerOfMonads {
/**
* Ultimate sum of squares method
*
* @param x First value in context
* @param y Second value in context
* @tparam F Monadic context
* @tparam T Type parameter in the Monad
* @return Sum of squares of first and second values in the Monadic context
*/
def sumOfSquares[F[_]: Monad, A, T >: A](x: F[A], y: F[A])(implicit num: Numeric[T]) : F[T] = {
def …Run Code Online (Sandbox Code Playgroud) 我有一个类似的课程
case class A(a: Int, b: String)
Run Code Online (Sandbox Code Playgroud)
和一个功能
def f(a: Int)(implicit b: String) =???
Run Code Online (Sandbox Code Playgroud)
可以这样做吗?
val a = A(11, "hello")
a match {
case A(a, implicit b) => f(a)
}
Run Code Online (Sandbox Code Playgroud)
如何在不提取后明确声明参数的情况下隐藏参数b.
Scala允许使用type关键字定义类型,这些类型通常具有不同的含义和目的,具体取决于声明的时间。
如果type在一个对象或一个包对象内部使用,则应定义一个类型别名,即另一种类型的简称/简称:
package object whatever {
type IntPredicate = Int => Boolean
def checkZero(p: IntPredicate): Boolean = p(0)
}
Run Code Online (Sandbox Code Playgroud)
在类/特征中声明的类型通常打算在子类/子特征中被覆盖,并且最终也被解析为具体类型:
trait FixtureSpec {
type FixtureType
def initFixture(f: FixtureType) = ...
}
trait SomeSpec extends FixtureSpec {
override type FixtureType = String
def test(): Unit = {
initFixture("hello")
...
}
}
Run Code Online (Sandbox Code Playgroud)
抽象类型声明还有其他用途,但无论如何最终它们都会解析为某些具体类型。
但是,还有一个选项可以在对象内部声明抽象类型(即,没有实际定义):
object Example {
type X
}
Run Code Online (Sandbox Code Playgroud)
与例如抽象方法相反,它可以编译:
object Example {
def method: String // compilation error
}
Run Code Online (Sandbox Code Playgroud)
由于无法扩展对象,因此永远无法将它们解析为具体类型。
我认为这样的类型定义可以方便地用作幻像类型。例如(使用Shapeless的标记类型):
import …Run Code Online (Sandbox Code Playgroud) 当我尝试通过隐式类为该类创建扩展并重载现有的通用方法时,它会因编译错误而失败:
error: overloaded method value getAs with alternatives:
(fieldName: String)String <and>
(i: Int)String
cannot be applied to (FooField.type)
r.getAs[String](FooField)
Run Code Online (Sandbox Code Playgroud)
通过隐式重载正常(非泛型)方法时,效果很好。在Scala 2.12.10上试用。链接到scastie。我想念什么?代码:
trait Row {
// Two overloads for `getAs[T]`
def getAs[T](i: Int): T
def getAs[T](fieldName: String): T
// Two overloads for `get`
def get(i: Int): String
def get(fieldName: String): String
}
trait Field {
def columnName: String
def columnDescription: String
}
case object FooField extends Field {
def columnName: String = "Foo"
def columnDescription: String = "Foo desc" …Run Code Online (Sandbox Code Playgroud) 给定以下 Peano 数的类型级加法函数
sealed trait Nat
class O extends Nat
class S[N <: Nat] extends Nat
type plus[a <: Nat, b <: Nat] = a match
case O => b
case S[n] => S[n plus b]
Run Code Online (Sandbox Code Playgroud)
说我们想证明定理
对于所有自然数 n,n + 0 = n
也许可以这样指定
type plus_n_0 = [n <: Nat] =>> (n plus O) =:= n
Run Code Online (Sandbox Code Playgroud)
那么在为定理提供证据时,我们可以很容易地向 Scala 编译器询问特定情况下的证据
summon[plus_n_O[S[S[O]]]] // ok, 2 + 0 = 2
Run Code Online (Sandbox Code Playgroud)
但是我们如何询问 Scala 是否可以为 的所有实例生成证据[n <: Nat],从而提供 的证明plus_n_0?
目前正在学习 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