使用《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) 我有一个计算数字类型的平方和的函数,如下所示。
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) 我正在扩展一个抽象类,它在其构造函数中定义了一个隐式参数。
似乎有 3 种不同的方法可以做到这一点:
abstract class Base(z: ZType)(implicit a: AType)
// Explicit
class First(z: ZType, a: Atype) extends Base(z)(a)
// Explicitly pass a into the child class which
// implicitly passes it into the parent class
class Second(z: ZType, implicit val a: AType) extends Base(z)
// Implicitly passed into both
class Third(z: ZType)(implicit a: AType) extends Base(z)
Run Code Online (Sandbox Code Playgroud)
也许这取决于将如何使用子类。就我而言,子类不会有隐含AType的作用域,所以我倾向于第二种选择。
我对第二个选项最大的担忧是,我现在为同一类型定义了 2 个隐式,一个在父类中,一个在子类中。由于它们始终是同一个对象,这有什么影响吗?出于任何原因,我应该避免第二种模式吗?
基本上,这里是否有“正确”的模式,或者所有这些都可以接受,具体取决于它们所使用的代码的上下文?
是否有任何客观原因可以/不在代码中到处使用隐式参数只是为了缩短应该传递的参数数量
我有一个 REST API。端点的每个调用都有一个唯一的 id,应该在调用触发的每个函数中逐字传递以进行调试。消除参数显式传递的第一个想法是使其成为每个函数中的隐式参数。但是,我的直觉告诉我,这是对隐式的误用(尽管我没有明确的论据不这样做)。
这种方法是否可以通过便利推理来证明,其中增益仅删除单个参数并假设对于像我这样的情况是一种很好的做法?
我正在尝试创建一个 ZIO 模块的示例,它有两个实现:
我的通用界面如下所示:
trait Service[R] {
def load[T <: Component](ref: CompRef): RIO[R, T]
}
Run Code Online (Sandbox Code Playgroud)
现在我的 YAML 实现看起来像:
def loadYaml[T <: Component: Decoder](ref: CompRef): RIO[Any, T] = {...}
Run Code Online (Sandbox Code Playgroud)
这Decoder是特定于实现的。
现在的问题是如何从 Service 实现委托给loadYaml.
我尝试了以下方法:
val components: Components.Service[Any] = new Components.Service[Any] {
implicit val decodeComponent: Decoder[Component] =
List[Decoder[Component]](
Decoder[DbConnection].widen,
...
).reduceLeft(_ or _)
def load[T <: Component](ref: CompRef): RIO[Any, T] = loadYaml[T] (ref)
}
Run Code Online (Sandbox Code Playgroud)
这给了我:
Error:(62, 20) could …Run Code Online (Sandbox Code Playgroud) 该阶语言规范,第7.2节是有关隐式范围:这解释了隐式范围内的是在某种方式与类型的部件相关联的模块T。下面列出了 T 的组成部分。其中之一是
if
T表示隐式转换为具有参数类型T1,…,Tn和结果类型的方法的类型U,T1,…,Tn 和 U 的部分的并集;
我不能从这个头或尾。我不明白类型 T 如何表示隐式转换。
隐式范围规范的这部分是什么意思?
当我在 Scala 中有一个函数时:
def toString[T: Show](xs: T*): String = paths.map(_.show).mkString
Run Code Online (Sandbox Code Playgroud)
以及范围内的以下类型类实例:
implicit val showA: Show[MyTypeA]
implicit val showB: Show[MyTypeB]
Run Code Online (Sandbox Code Playgroud)
我可以通过toString以下方式使用函数:
val a1: MyTypeA
val a2: MyTypeA
val stringA = toString(a1, a2)
val b1: MyTypeB
val b2: MyTypeB
val stringB = toString(b1, b2)
Run Code Online (Sandbox Code Playgroud)
但我不能叫toString混合型的参数MyTypeA和MyTypeB:
// doesn't compile, T is inferred to be of type Any
toString(a1, b1)
Run Code Online (Sandbox Code Playgroud)
是否有可能以toString一种可以混合不同类型的参数(但仅限于Show类型类可用)的方式重新定义?
请注意,我知道 cat show interpolator 可以解决这个特定的例子,但我正在寻找一种也可以应用于不同情况的解决方案(例如toNumber)。
我也知道通过.show在将参数传递给toString …
给定以下 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我需要通过隐式深层链接将数据模型从一个片段传递到另一个片段,但我没有找到一种方法。我只找到这样的东西:
val request = NavDeepLinkRequest.Builder
.fromUri("android-app://androidx.navigation.app/profile".toUri())
.build()
findNavController().navigate(request)
Run Code Online (Sandbox Code Playgroud)
但它没有方法传递包/模型或类似的东西。有人可以帮忙吗?
编辑。我的情况:我需要从功能模块的片段导航到应用程序模块的片段。应用程序模块的该片段接受特定的数据模型。我无法依赖应用程序模块,因此我无法直接访问该片段。这就是为什么我需要隐式深度链接来导航,并且需要传递数据模型。
关于反模式,它是一个巨大的项目,并且该片段在很多地方使用,所以我无法更改它。
implicit ×10
scala ×8
scala-3 ×2
scala-cats ×2
typeclass ×2
android ×1
casting ×1
circe ×1
deep-linking ×1
given ×1
kotlin ×1
monads ×1
navigation ×1
polymorphism ×1
swift ×1
swift3 ×1
syntax ×1
types ×1
zio ×1