请考虑以下代码:
object foo {
trait Bar[Q[_]]
implicit object OptionBar extends Bar[Option]
def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()
def main(args: Array[String]) {
test(Some(42): Option[Int]) //???
}
}
Run Code Online (Sandbox Code Playgroud)
这是有效的,但我需要输入Some(42)作为Option [Int],否则隐式对象OptionBar将不会被解析(因为预期会改为Bar [Some]).有没有办法避免显式输入,所以我在测试中得到隐含的OptionBar对象,即使我用Some或None提供测试?
[澄清]
Bar抽象类等它也应该工作.implicit object listBar extends Bar[list][更新]
似乎使Bar的参数逆变成功了:
object foo {
trait Bar[-Q[_]] //<---------------
implicit object OptionBar extends Bar[Option]
implicit object ListBar extends Bar[List]
def test[T, C[_]](c: C[T])(implicit bar: Bar[C]) = ()
def main(args:Array[String]) {
test(Some(42))
}
}
Run Code Online (Sandbox Code Playgroud)
但当然这是对Bar的可能性的严重限制,所以我仍然希望得到更好的答案.
我在某些情况下使用类型类设计API但是我遇到了隐式解析的问题.如下所示,如果存在类型A的隐式对象但是将类型的对象B extends A传递给该方法,则无法找到隐式对象.有没有办法使这项工作或调用者必须将隐式对象放入每个子类的范围?
这是一个例子:
class A
class B extends A
class T[+X]
object T {
implicit object TA extends T[A]
}
def call[X:T](x:X) = println(x)
// compiles
call(new A)
// doesn't compile
call(new B)
var a = new A
// compiles
call(a)
a = new B
// compiles
call(a)
val b = new B
// doesn't compile
call(b)
Run Code Online (Sandbox Code Playgroud)
无法使用以下输出进行编译:
/private/tmp/tc.scala:16: error: could not find implicit value for evidence parameter of type this.T[this.B]
call(new B)
^
/private/tmp/tc.scala:28: error: could … 假设我想包装可以使用try-catch块抛出异常的代码,该块记录异常并继续.就像是:
loggingExceptions {
// something dangerous
}
Run Code Online (Sandbox Code Playgroud)
理想情况下,我想用于记录调用对象上定义的Logger(如果有的话)(如果没有,则会产生编译时错误).我喜欢定义这样的东西:
def loggingExceptions[L <: { def logger: Logger }](work: => Unit)(implicit objectWithLogger: L): Unit = {
try {
work
} catch {
case t: Exception => objectWithLogger.logger.error(t.getMessage)
}
}
Run Code Online (Sandbox Code Playgroud)
其中objectWithLogger会以某种方式"神奇地"在客户端代码中扩展为"this".这个(或类似的东西)可能吗?
考虑Haskell(GHC)中的隐式参数,我遇到了问题.我有一个函数f,它假定隐含参数x,并希望通过将f应用于g来将其封装在上下文中
f :: (?x :: Int) => Int -> Int
f n = n + ?x
g :: (Int -> Int) -> (Int -> Int)
g t = let ?x = 5 in t
Run Code Online (Sandbox Code Playgroud)
但是当我试图评估时
g f 10
Run Code Online (Sandbox Code Playgroud)
我得到一个x没有绑定的错误,例如:
Unbound implicit parameter (?x::Int)
arising from a use of `f'
In the first argument of `g', namely `f'
In the second argument of `($)', namely `g f 10'
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我,我做错了什么?
(我试图让Haskell的WordNet接口工作 - …
我一直在使用Scala中的类型类模式,但是当我使用的类型是通用的时,我无法弄清楚如何实现隐式伴随对象.
例如,假设我已经为类型类定义了一个特征,它提供了将事物放入Boxes的函数.
case class Box[A](value: A)
trait Boxer[A] {
def box(instance: A): Box[A]
def unbox(box: Box[A]): A
}
implicit object IntBoxer extends Boxer[Int] {
def box(instance: Int) = Box(instance)
def unbox(box: Box[Int]) = box.value
}
def box[A : Boxer](value: A) = implicitly[Boxer[A]].box(value)
def unbox[A : Boxer](box: Box[A]) = implicitly[Boxer[A]].unbox(box)
Run Code Online (Sandbox Code Playgroud)
这按预期工作,允许我提供Boxer各种类型的实现.但是,当我想要采取的类型本身就是通用的时候,我不知道如何做到这一点.假设我想能够使用我Boxer的任何一个Seq[A].objectScala中的s不能包含类型参数,所以我不知道该去哪里:
// Will not compile - object cannot have type arguments
implicit object SeqBoxer[A] extends Boxer[Seq[A]] { ... } …Run Code Online (Sandbox Code Playgroud) 是否有三元运算符参数的隐式类型转换规则?
三元运算符总是需要返回相同的类型.此类型仅由第二个和第三个参数(1st ? 2nd : 3rd)确定,因此两个参数都转换为此类型.这种类型是如何确定的?
更具体地说,我测试了一个例子:
class pointclass
{
pointclass();
pointclass( int i ); // (pointclass)(int)
operator bool() const; // (bool)(pointclass)
};
Run Code Online (Sandbox Code Playgroud)
我有一个类(pointclass),它使从隐式转换int到pointclass和从隐式转换pointclass到bool.
int i;
pointclass p;
bool b;
b ? p : i; // (bool) ? (int)(bool)(pointclass) : (int)
b ? i : p; // (bool) ? (int) : (int)(bool)(pointclass)
Run Code Online (Sandbox Code Playgroud)
使用三元运算符,我比较pointclass和int.编译器使用从隐式转换pointclass到bool,然后从标准转换bool到int.无论我是否交换第二和第三个参数,这都已完成.为什么不转换int为 …
我有一个形式的构造函数:
MyClass(int a,int b,int c);
并使用以下代码调用它:
MyClass my_object(4.0,3.14,0.002);
我想阻止这种从double到int的自动转换,或者至少在编译时得到警告.
似乎"显式"关键字在这些情况下不起作用,对吧?
我需要将两个函数作为参数传递给scala函数.然后,该函数应对它们进行评估并从中获取一个数字,然后对其进行操作.此数字可以是Int,Double或任何其他数字类型.无论它使用什么类型,我都希望该功能能够正常工作.
下面的例子解释了这个问题.
import Numeric.Implicits._
class Arithmetic[T : Numeric](val A: Connector[T], val B: Connector[T]) {
val sum = new Connector({ A.value + B.value })
}
class Constant[T](var x: T) {
val value = new Connector({ x })
}
class Connector[T](f: => T) {
def value: T = f
override def toString = value.toString()
}
object Main extends App{
val n1 = new Constant(1)
// works
val n5 = new Constant(5)
val a = new Arithmetic( n1.value, n5.value )
println(a.sum)
// no …Run Code Online (Sandbox Code Playgroud) 我一直试图了解隐式参数在Scala中的工作原理.据我所知,隐式参数解析如下:
然而,当我开始玩这个懒惰的vals时,我得到了一些帮助.懒惰的val似乎只使用最后的解析规则.以下是一些示例代码:
class Bar(val name:String)
object Bar { implicit def bar = new Bar("some default bar") }
class Foo {
lazy val list = initialize
def initialize(implicit f:Bar) = {
println("initialize called with Bar: '" + f.name + "' ...")
List[Int]()
}
}
trait NonDefaultBar extends Foo {
implicit def f = new Bar("mixed in implicit bar")
def mixedInInit = initialize
lazy val mixedInList = list
}
object Test {
def test = {
println("Case 1: with …Run Code Online (Sandbox Code Playgroud) 我正在使用隐式def来构建递归HList类型,以匹配几种更高级的类型HList.我很受这篇文章的启发.
这段代码完美运行:
sealed trait HList {
type Plus[L <: HList] <: HList
}
class HNil extends HList {
type Plus[L <: HList] = L
def ::[T](v: T) = HCons(v, this)
}
case class Appender[L1 <: HList, L2 <: HList, R <: HList](fn: (L1, L2) => R) {
def apply(l1: L1, l2: L2) = fn(l1, l2)
}
object HNil extends HNil
object HList {
def ++[L1 <: HList, L2 <: HList](l1: L1, l2: L2)(implicit f: …Run Code Online (Sandbox Code Playgroud) implicit ×10
scala ×7
c++ ×2
generics ×2
parameters ×2
typeclass ×2
casting ×1
constructor ×1
ghc ×1
haskell ×1
inheritance ×1
numeric ×1
ternary ×1
types ×1
wordnet ×1