标签: implicits

如何为隐式方法实现中间类型?

假设我想fooA我控制之外的现有类型上提供方法.据我所知,在Scala中执行此操作的规范方法是实现从A实现的某种类型的隐式转换foo.现在我基本上看到两个选项.

  1. 为此目的定义一个单独的,甚至是隐藏的类:

    protected class Fooable(a : A) {
      def foo(...) = { ... }
    }
    implicit def a2fooable(a : A) = new Fooable(a)
    
    Run Code Online (Sandbox Code Playgroud)
  2. 定义内联匿名类:

    implicit def a2fooable(a : A) = new { def foo(...) = { ... } }
    
    Run Code Online (Sandbox Code Playgroud)

变体2)肯定是较少的样板,特别是当发生许多类型参数时.另一方面,我认为它应该创建更多的开销,因为(概念上)每个转换创建一个类,而不是1)中的一个全局类.

有一般指导方针吗?没有区别,因为编译器/ VM摆脱了2)的开销?

scala implicits

3
推荐指数
2
解决办法
313
查看次数

Scala的含义是否可以转换为更高级别的类型?

假设我有一个名为LongArrayWritable的类型,它是一个Longs数组的盒装表示.我有隐式定义,在这些类型之间转换:

implicit def boxLongArray(array: Array[Long]) : LongArrayWritable { /*elided*/}
implicit def unboxLongArray(array: LongArrayWritable) : Array[Long] { /*elided*/}
Run Code Online (Sandbox Code Playgroud)

现在,我也有一些暗示,它们以通用形式在java.lang.Iterable和scala.collection.List [X]之间进行转换:

implicit def iterator2list[X](it : java.lang.Iterable[X]) : List[X] { /* elided */ }
implicit def list2iterator[X](list : List[X]) : java.lang.Iterable[X] { /* elided */ }
Run Code Online (Sandbox Code Playgroud)

使用这些定义,scala编译器可以推断java.lang.Iterable [LongArrayWritable]和List [Array [Long]](相当于iterator2list(iterator).map(unboxLongArray(_)))之间的隐式转换,或者这超出了implicits的功能,因此需要它自己的(显式?)隐式定义?

谢谢,

蒂姆

generics types scala implicits

3
推荐指数
1
解决办法
482
查看次数

两个看似相同的语义:一个隐式绑定,另一个不绑定

您好:我最近一直在学习Scala(我的相关背景主要是在C++模板中),而且我遇到了一些我目前对Scala不了解的事情,这让我感到疯狂.:(

(另外,这是我在StackOverflow上的第一篇文章,我注意到大多数真正令人敬畏的Scala人似乎都在闲逛,所以如果我对这个机制做了一些非常愚蠢的事情,我真的很抱歉.)

我的具体困惑与隐式参数绑定有关:我提出了一个特定的情况,其中隐式参数拒绝绑定,但具有看似相同的语义的函数确实如此.

现在,它当然可能是一个编译器错误,但鉴于我刚开始使用Scala,我已经遇到某种严重错误的可能性非常小,我期待有人解释我做错了什么.,P

我已经完成了代码并将其削减了很多,以便提出一个不起作用的单个示例.不幸的是,这个例子仍然相当复杂,因为问题似乎只发生在概括中.:(

1)简化的代码不能按我预期的方式工作

import HList.::

trait HApplyOps {
    implicit def runNil
        (input :HNil)
        (context :Object)
        :HNil
    = {
        HNil()
    }

    implicit def runAll[Input <:HList, Output <:HList]
        (input :Int::Input)
        (context :Object)
        (implicit run :Input=>Object=>Output)
        :Int::Output
    = {
        HCons(0, run(input.tail)(context))
    }

    def runAny[Input <:HList, Output <:HList]
        (input :Input)
        (context :Object)
        (implicit run :Input=>Object=>Output)
        :Output
    = {
        run(input)(context)
    }
}

sealed trait HList

final case class HCons[Head, Tail <:HList]
    (head :Head, tail :Tail)
    extends HList
{
    def ::[Value](value :Value) = …
Run Code Online (Sandbox Code Playgroud)

scala implicits

3
推荐指数
1
解决办法
691
查看次数

如何在Scala中以递归方式应用隐含转换

我正在尝试编写一个转换库,用于将一些scala类型转换为HTML表示.比方说,我想要执行List(1,2).toHtml和获取<ul><li>1</li><li>2</li></ul>,作为一个String.
到目前为止,我已经编写了一组隐式转换,它们可以很好地检测结果类型并应用正确的结果toHtml.

让我展示一个示例:

object Conversions {

  implicit def fromIterable[A](l : Iterable[A]) = new Object {
       def toHtml = <ul> { l.map{ e => <li>{ e }</li> } } </ul> toString
  }
}
import Conversions._
Run Code Online (Sandbox Code Playgroud)

有了这段代码,每当我问编译器时,List(1,2).toHtml我得到正确的转换.就像任何其他Iterableval一样.

我的问题和问题是如何递归地使用这个toHtml转换?因为如果我输入List( List(1,2), List(3,4) ).toHtml我想要获得<ul> <li><ul><li>1</li><li>2</li></ul></li> <li><ul><li>3</li><li>4</li></ul></li> </ul>,toHtml转换应用递归地应用于输入的每个元素Iterable.

我试图将toHtml定义更改为def toHtml = <ul> { l.map{ e => <li>{ e.toHtml }</li> } } </ul> toString …

recursion scala implicits

3
推荐指数
1
解决办法
195
查看次数

Scala spray-client定义了AKKA ActorRefFactory的含义

我正在尝试使用Scala和spray-client编写一个简单的HTTP客户端.我的客户基于Spray文档上给出的示例.

我的问题是该示例是创建一个新的隐式 ActorSystem即

implicit val system = ActorSystem()
Run Code Online (Sandbox Code Playgroud)

但我希望我的客户端可以重用,而不是创建一个新的ActorSystem.

这是我的代码的要点.

trait WebClient {
  def get(url: String)(implicit system: ActorSystem): Future[String]
}

object SprayWebClient extends WebClient {
  val pipeline: HttpRequest => Future[HttpResponse] = sendReceive

  def get(url: String): Future[String] = {
    val r = pipeline (Get("http://some.url/"))
    r.map(_.entity.asString)
  }

}
Run Code Online (Sandbox Code Playgroud)

但我得到两个关于implicits的编译器错误

implicit ActorRefFactory required: if outside of an Actor you need an implicit ActorSystem, inside of an actor this should be the implicit ActorContext WebClient.scala ...
Run Code Online (Sandbox Code Playgroud)

not enough arguments for …
Run Code Online (Sandbox Code Playgroud)

scala actor akka implicits spray

3
推荐指数
1
解决办法
4276
查看次数

play json写子类给出了模糊隐含值的错误

我正在使用play框架,并有一个抽象类:

 abstract class Base{...}
Run Code Online (Sandbox Code Playgroud)

在伴随对象中有自己的隐式JSON编写器

object Base {
   implicit val baseWrites: Writes[Base] = (...)(unlift(Base.unapply))
}
Run Code Online (Sandbox Code Playgroud)

我是这个抽象类的子类:

case class SubClass{...}
Run Code Online (Sandbox Code Playgroud)

在其伴随对象中也有自己的隐式JSON编写器

object SubClass {
   implicit val subClassWrites: Writes[SubClass] = (...)(unlift(SubClass.unapply))
}
Run Code Online (Sandbox Code Playgroud)

当我尝试使用Json.toJson(SubClass)序列化子类对象时,我收到一个错误:

[error]  both value subClassWrites in object SubClass of type => play.api.libs.json.
Writes[models.SubClass]
[error]  and value baseWrites in object Base of type =>        
play.api.libs.json.Writes[models.Base]
[error]  match expected type play.api.libs.json.Writes[models.SubClass]
[error]  Ok(Json.toJson(SubClass.find(id)))
Run Code Online (Sandbox Code Playgroud)

有没有办法消除歧义?

json scala implicits playframework playframework-2.0

3
推荐指数
1
解决办法
2239
查看次数

周围范围的隐式参数解析

我不喜欢将隐式参数引入我的代码中,所以在我使用它们时我想封装它们的用法.所以我试图定义一个对象,它既包含对异常处理的spray-json的调用,又包含每个模型类的默认隐式JsonFormats.但是,隐式参数不会被解析,除非它们被导入到客户端,调用代码,这正是我不想要它们的地方.这是我到目前为止(它没有解决隐式格式化程序),有没有办法让我得到我想要的工作?

package com.rsslldnphy.json

import com.rsslldnphy.models._
import spray.json._

object Json extends DefaultJsonProtocol {

  implicit val personFormat = jsonFormat1(Person)
  implicit val animalFormat = jsonFormat1(Animal)

  def parse[T](s:String)(implicit reader: JsonReader[T]): Option[T] = {
    try { Some(JsonParser(s).convertTo[T]) }
    catch { case e: DeserializationException => None }
  }
}
Run Code Online (Sandbox Code Playgroud)

NB.JsonFormat是一种JsonReader

编辑:这是我根据@ paradigmatic的第二个建议(我无法工作,我仍然得到Cannot find JsonReader or JsonFormat type class for T)写的.我错过了什么吗?

object Protocols extends DefaultJsonProtocol {
  implicit val personFormat = jsonFormat1(Person)
  implicit val animalFormat = jsonFormat1(Animal)
}

object Json {

  def parse[T](s:String): Option[T] = { …
Run Code Online (Sandbox Code Playgroud)

scala implicits spray-json

2
推荐指数
1
解决办法
2460
查看次数

Scala隐式参数的Groovy等价物

是否有一些Groovy替代方案来表达如下内容:

def doSomethingWith(implicit i:Int) = println ("Got "+i)
implicit var x = 5

doSomethingWith(6)  // Got 6
doSomethingWith     // Got 5

x = 0
doSomethingWith     // Got 0
Run Code Online (Sandbox Code Playgroud)

更新:请参阅此处的后续问题:Groovy等效于Scala隐式参数 - 扩展

groovy scala implicits

2
推荐指数
1
解决办法
432
查看次数

使用-Ywarn-unused时,从Scala中的分析中排除类型证据参数

T <:< U-Ywarn-unused传递给编译器时,在Scala中编译包含类型证据参数的程序(例如)可能会引起警告。特别是在类型证据参数用于验证使用幻像类型编码的约束的情况下,很可能会发生此警告。

例如,在此处编译文件:https : //github.com/hseeberger/demo-phantom-types/blob/master/src/main/scala/de/heikoseeberger/demophantomtypes/Hacker.scala返回以下内容:

# scalac -Ywarn-unused Hacker.scala Hacker.scala:42: warning: parameter value ev in method hackOn is never used def hackOn(implicit ev: IsCaffeinated[S]): Hacker[State.Decaffeinated] = { ^ Hacker.scala:47: warning: parameter value ev in method drinkCoffee is never used def drinkCoffee(implicit ev: IsDecaffeinated[S]): Hacker[State.Caffeinated] = { ^ two warnings found

对我来说很明显,该参数ev实际上不是在运行时必需的,但在编译时该参数很有用。有什么方法可以指示编译器忽略这种情况,同时在其他情况下仍对未使用的函数参数提出警告?

例如,我认为指示编译器忽略类的隐式参数<:<=:=将解决此问题,但是我不确定如何实现。

scala compiler-warnings implicits phantom-types unused-variables

2
推荐指数
1
解决办法
341
查看次数

惯用的分支方式取决于Scala中类型证据的存在

我发现自己不止一次写下以下丑陋的模式:

class Something[A, B](implicit ev: A =:= B = null) {
  ...

  def doStuff {
    if (ev == null) ... // know that A is not the same as B
    else ...            // safely assume A is equal to B
  }
}
Run Code Online (Sandbox Code Playgroud)

更糟糕的是,何时ev != null,我有时会写出诸如此类的异端邪说someB.asInstanceOf[A].

types scala implicits

1
推荐指数
1
解决办法
107
查看次数