我正在阅读Joshua D. Suereth的Scala In Depth,并且在scala中遇到了关于隐式视图的以下代码:
object test {
trait Foo
trait Bar
object Foo {
implicit def fooToBar(f : Foo) = new Bar{ }
}
}
Run Code Online (Sandbox Code Playgroud)
然后定义一个需要Bar作为参数的方法:
def bar(x : Bar) = println("bar")
Run Code Online (Sandbox Code Playgroud)
为什么以下工作:
val f = new Foo{}
bar(f) // print "bar"
Run Code Online (Sandbox Code Playgroud)
但
bar(new Foo{})
Run Code Online (Sandbox Code Playgroud)
会导致编译器给出类型不匹配错误:
error: type mismatch;
found : java.lang.Object with test.Foo
required: test.Bar
bar(new Foo {})
^
Run Code Online (Sandbox Code Playgroud) 我正在尝试使用隐式参数将依赖项"注入"到我的类中,如下所示:
trait Bar {
def m:String
}
object Bar {
implicit val objBar = new Bar{ val m = "from object" }
}
trait FooTrait {
def aBar(implicit bar:Bar) = bar
def go = { aBar.m }
}
Run Code Online (Sandbox Code Playgroud)
这里编译器FooTrait从Bar伴随对象中的隐式val 提供隐式参数.这样做:
scala> println((new FooTrait{}).go)
from object
Run Code Online (Sandbox Code Playgroud)
给我我期望的结果.但是,如果我混合FooTrait和另一个特征如:
trait SuperFoo {
implicit val superBar = new Bar{ val m = "from super" }
}
Run Code Online (Sandbox Code Playgroud)
结果是一样的:
scala> println((new FooTrait with SuperFoo).go)
from object
Run Code Online (Sandbox Code Playgroud)
我认为编译器会SuperFoo在尝试通过检查Bar的伴随对象来解析隐式参数之前查看.这篇博客文章 …
考虑:
object implicitnull extends App {
mymethod
implicit val arg = "foo"
def mymethod(implicit arg: String) = {
arg.size
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这不会导致任何编译错误,而是在运行时导致NullPointerException来自arg.size.
这是预期的行为吗?
据我所知,有两种方法可以添加类型约束.
trait Dummy
Run Code Online (Sandbox Code Playgroud)
第一种方式
def doStuff[T <: Dummy](x: T) = x
Run Code Online (Sandbox Code Playgroud)
第二种方式
def doStuff[T](x: T)(implicit x: T <:< Dummy) = x
Run Code Online (Sandbox Code Playgroud)
两者都达到了相同的效果.
我只是想知道我应该直接使用上限或下限的哪种场景,或者我应该使用implicit来在类型上附加约束.
一件奇怪的事情正在发生。我定义了语法,这是节选。
name
: Letter
| Digit name
| Letter name
;
numeral
: Digit
| Digit numeral
;
fragment
Digit
: [0-9]
;
fragment
Letter
: [a-zA-Z]
;
Run Code Online (Sandbox Code Playgroud)
那么为什么它只对我引用一个片段的两行(字母和数字名称)显示警告,而下面的其他行完全正确...
我正在尝试构建DSL,但我遇到了一个问题:它适用于案例类,但我想知道提取案例类字段名称的最简单方法.我想到的一个想法是使用宏来丰富我的Case类的类型,但我不愿意.
trait QueryDSL[CC] {
def meta: CC
implicit object StringIsFieldType extends Field[CC, String] {
def name = "FakeNAME"
}
implicit def implQuery[V](b: V): Query[CC] = new Query[CC](meta)
implicit def implField[V](b: V)(implicit ev: Field[CC, V]): QueryField[CC, V] = new QueryField(ev)
}
case class Query[CC](meta: CC, clauses: List[Clause[_]] = Nil) {
def setProperty[F](clause: CC ? Clause[F]): Query[CC] = copy(clauses = clause(meta) :: clauses)
}
trait Field[V, M] extends scala.AnyRef {
def name: scala.Predef.String
}
abstract class Clause[V](val fieldName: String, value: V)
case …Run Code Online (Sandbox Code Playgroud) 类型级别foldRight工作正常(getLabelWithValues),后续类型级别map(getValues)也可以正常工作.如果我在一个方法(getValuesFull)中组合两者,它就不再起作用了.丢失的是什么?
完整的源代码(sbt准备好~run使用隐式调试输出)在这里:https://github.com/mpollmeier/shapeless-playground/tree/8170a5b
case class Label[A](name: String)
case class LabelWithValue[A](label: Label[A], value: A)
val label1 = Label[Int]("a")
val labels = label1 :: HNil
object combineLabelWithValue extends Poly2 {
implicit def atLabel[A, B <: HList] = at[Label[A], (B, Map[String, Any])] {
case (label, (acc, values)) ?
(LabelWithValue(label, values(label.name).asInstanceOf[A]) :: acc, values)
}
}
object GetLabelValue extends (LabelWithValue ~> Id) {
def apply[B](labelWithValue: LabelWithValue[B]) = labelWithValue.value
}
val labelsWithValues: LabelWithValue[Int] :: HNil = getLabelWithValues(labels) …Run Code Online (Sandbox Code Playgroud) 当Scala的调用implicitly在运行时返回null时,我最近感到很惊讶.我认为这是不可能的,因为如果在隐式范围内没有可用的隐式实例,代码就不应该编译.何时隐式允许返回null?这是编译器限制,还是这种预期的行为?
如果有帮助,这里有一些背景信息.我正在使用无形来派生类型类实例来持久化任意嵌套的case类.我认为在嵌套的case类中隐式使用来检查是否可以派生类型类实例是有帮助的,因为可能不清楚从哪里开始查看嵌套的case类是否很大.
所以,例如,如果我试图坚持:
case class Foo(bar: Bar, baz: Baz)
Run Code Online (Sandbox Code Playgroud)
并且编译器无法为我的格式化程序派生一个实例MyFormatter[Foo],我开始做类似以下的事情:
case class Bar(i: Int, q: Qux)
object Bar {
implicit val formatter = implicitly[MyFormatter[Bar]]
}
Run Code Online (Sandbox Code Playgroud)
期望编译器告诉我它找不到隐式实例MyFormatter[Bar].
相反,这是一个可怕的想法,我的代码编译(当它不应该,因为没有Qux的类型类实例可以派生)并且Bar.formatter在运行时为null.
我试图让隐式流程为IdentityServer4工作.登录和注销正常工作,但PostLogoutRedirectUri返回null,尽管设置了需要设置的值.我想要的是注销过程在注销完成后重定向回我的应用程序.
我正确获取logoutId,Logout调用BuildLoggedOutViewModelAsync:
[HttpPost]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout(LogoutInputModel model)
{
var vm = await _account.BuildLoggedOutViewModelAsync(model.LogoutId);
...
Run Code Online (Sandbox Code Playgroud)
此方法位于我的AccountService.cs类中,然后调用DefaultIdentityServiceInteractionService的GetLogoutContextAsync:
public async Task<LoggedOutViewModel> BuildLoggedOutViewModelAsync(string logoutId)
{
// get context information (client name, post logout redirect URI and iframe for federated signout)
var logout = await _interaction.GetLogoutContextAsync(logoutId);
...
Run Code Online (Sandbox Code Playgroud)
这会创建一个IdentityServer4.Models.LogoutRequest.
该SignOutIFrameUrl字符串属性设置为"http://localhost:5000/connect/endsession/callback?sid=bf112f7785bc860fcc4351893012622e&logoutId=d6649e7f818d9709b2c0bc659696abdf",但没有别的似乎都在LogoutRequest被填充.
不幸的是,这意味着它PostLogoutRedirectUri是null并且AutomaticRedirectAfterSignOut也是null,并且当LoggedOut.cshtml加载页面时,signout-callback.js永远不会加载该文件:
@section scripts
{
@if (Model.AutomaticRedirectAfterSignOut)
{
<script src="~/js/signout-redirect.js"></script>
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的配置设置.
Config.cs:
public static IEnumerable<Client> GetClients()
{
return new List<Client>
{ …Run Code Online (Sandbox Code Playgroud) 此代码无法编译:
object Foo {
implicit def toString(i: Int): String = i.toString
def foo(x: String) = println(x)
foo(23)
}
Run Code Online (Sandbox Code Playgroud)
上面的代码无法编译,但有以下错误:
error: type mismatch;
found : scala.this.Int(23)
required: String
foo(23)
Run Code Online (Sandbox Code Playgroud)
但是,这段代码编译
object Foo {
implicit def asString(i: Int): String = i.toString
def foo(x: String) = println(x)
foo(23)
}
Run Code Online (Sandbox Code Playgroud)
为什么名称implicit def应该重要?
注意:如果该方法被命名equals,它也不会工作,但它的作品,如果它被命名hashCode或clone等
implicit ×10
scala ×8
shapeless ×2
antlr ×1
c# ×1
case-class ×1
definition ×1
dsl ×1
parsing ×1
scala-macros ×1
token ×1
typeclass ×1