在尝试使用应用程序仿函数进行验证时(Monad捕获多个异常(不仅仅是单个失败)),我在scalaz中遇到了一个禁止超过14个仿函数的硬限制,所以这里有一个有用的注释(https:// github .com/scalaz/scalaz/issues/504#issuecomment-23626237)导航我使用HLists而不是applicative functor
现在它工作得非常好(从此处手动输入此序列文件,因为它不在maven https://github.com/typelevel/shapeless-contrib/blob/master/scalaz/main/scala/sequence.scala?来源= c)
我的问题是,我知道这是可能的,你怎么会自动实例化case class Foo(i:Int,s:String)而不必手动匹配模式与案例,只是再次重新应用参数
基本上我想做这样的事情
case class Foo(i:Int,s:String)
implicit def TwoFoo = Iso.hlist(Foo.apply _, Foo.unapply _)
val someFoo = sequence(
1.successNel[Int] ::
"2".successNel[String] ::
HNil
).map { Foo.apply _} // Note this doesn't work
someFoo match {
case Success(a) => println(a)
case Failure(a) => {
println("failure")
println(a)
}
}
Run Code Online (Sandbox Code Playgroud) 感谢https://github.com/milessabin/shapeless/wiki/Feature-overview:-shapeless-2.0.0我理解如何压缩无形的HLists:
从Shapeless 2.0.0-M1导入一些东西:
import shapeless._
import shapeless.ops.hlist._
import syntax.std.tuple._
import Zipper._
Run Code Online (Sandbox Code Playgroud)
创建两个HLists:
scala> val h1 = 5 :: "a" :: HNil
h1: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 5 :: a :: HNil
scala> val h2 = 6 :: "b" :: HNil
h2: shapeless.::[Int,shapeless.::[String,shapeless.HNil]] = 6 :: b :: HNil
Run Code Online (Sandbox Code Playgroud)
拉链他们:
scala> (h1, h2).zip
res52: ((Int, Int), (String, String)) = ((5,6),(a,b))
Run Code Online (Sandbox Code Playgroud)
现在尝试定义一个执行相同操作的函数:
scala> def f[HL <: HList](h1: HL, h2: HL) = (h1, h2).zip
f: [HL <: shapeless.HList](h1: HL, h2: HL)Unit
Run Code Online (Sandbox Code Playgroud)
推断的返回类型是Unit,实际上将f应用于h1和h2就是这样:
scala> …Run Code Online (Sandbox Code Playgroud) 我有一个Nat的HList,我想要映射它
object NatToString extends Poly1 {
implicit def caseNat = at[Nat](_.toString)
}
val list = _5 :: _3 :: HNil
list.map(NatToString)
Run Code Online (Sandbox Code Playgroud)
此代码不编译并抛出:
找不到参数映射器的隐含值:
shapeless.ops.hlist.Mapper [Main.Nat_to_String.type,shapeless.:: [shapeless.Nat._5,shapeless.:: [shapeless.Nat._3,shapeless.HNil]] ]
但是,如果我用Int(或String,或List等)代替Nat做同样的事情,它就完美无缺.
我如何映射Nat的HList?
是否可以使用Shapeless从案例类中提取特定类型的值?到目前为止,我可以这样做:
def fromCaseClass[T, R <: HList](value: T)(implicit ga: Generic.Aux[T, R]): R = {
ga.to(value)
}
Run Code Online (Sandbox Code Playgroud)
然后,这允许我在程序上提取值:
scala> case class ServiceConfig(host: String, port: Int, secure: Boolean)
defined class ServiceConfig
scala> val instance = ServiceConfig("host", 80, true)
instance: ServiceConfig = ServiceConfig(host,80,true)
scala> fromCaseClass(instance).select[Boolean]
res10: Boolean = true
scala> fromCaseClass(instance).select[Int]
res11: Int = 80
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试编写一个函数来执行此操作时,我会遇到未找到的implicits:
def getByType[C, X](value: C)(implicit ga: Generic.Aux[C, X]): X = {
fromCaseClass(value).select[X]
}
<console>:12: error: could not find implicit value for parameter ga: shapeless.Generic.Aux[C,R]
fromCaseClass(value).select[X]
Run Code Online (Sandbox Code Playgroud)
据推测我得到的是因为编译器无法验证我的参数不是case类.有没有办法让我这样做?
我对Shapeless很陌生,所以我不能完全确定我是在尝试做一些疯狂的事情,还是想错过一些简单的事情.
我觉得我离得更近了.我可以这样实现: …
这两个记录具有相同的字段,具有相同的值,但顺序不同:
val person1 = ("age" ->> 34) :: ("name" ->> "Jane") :: HNil
val person2 = ("name" ->> "Jane") :: ("age" ->> 34) :: HNil
Run Code Online (Sandbox Code Playgroud)
当我使用时,这些被认为是相等的,==因为字段的顺序是不同的.它们是HLists,所以在检查相等性时,顺序对我来说是有意义的,但我觉得彼此排列的记录应该是平等的.我也觉得他们应该有相同的类型,但他们没有,因为他们是HList.
有没有办法让记录的值和类型相等,更像我期望的行为?另外,这种方式实施的原因是什么?可以HMap使用吗?
我对Shapeless很新,因为我会从我的问题中推断出来.给定一个实例LabelledGeneric,如何获取它所代表的类的名称.我可以从中获取字段名称信息Keys,所以我假设我需要一些其他类型的Witness封装类型本身,但我无法弄清楚哪个.
例如,如果我在包com.bar中有一个名为Foo的case类,我想得到字符串"com.bar.Foo"(或单独就可以了).
implicit def example[T, Repr <: HList](implicit label: LabelledGeneric.Aux[T, Repr],
kk: Keys[Repr]): Bibble[T] = new Bibble[T] {
override def typeName(value: T): String = ???
}
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.
在以下示例中
import shapeless._
import shapeless.syntax.singleton._
val concat = "right".narrow
def extract[s <: String](x: s)(implicit witness: Witness.Aux[s]): String = witness.value
extract(concat)
Run Code Online (Sandbox Code Playgroud)
我收到了一个错误
错误:找不到参数的隐含值
witness:shapeless.Witness.Aux[String("right")]
我正在尝试做的事情是类型级DSL,它严重依赖单例类型.
由于在typelevel的fork之外支持单例类型的文字,我希望除了类型文字之外还要开发基于值的DSL,并且在值类型中保留可用的单例类型对于此任务至关重要.
所以我正在寻找允许我稍后从值的类型中提取单例字符串见证的任何解决方法.
操作使用.witness而不是.narrow完美地工作,但我仍然在寻找纯粹类型的解决方案,而不需要Witness包装
鉴于:
scala> import shapeless.nat.
_0 _10 _12 _14 _16 _18 _2 _21 _3 _5 _7 _9 natOps
_1 _11 _13 _15 _17 _19 _20 _22 _4 _6 _8 apply toInt
scala> import shapeless.ops.nat._
import shapeless.ops.nat._
Run Code Online (Sandbox Code Playgroud)
> 3分钟后,以下代码未编译/运行.为什么?
scala> Sum[_22, _22]
Run Code Online (Sandbox Code Playgroud)
另外,看看上面的REPL自动完成,_44甚至存在于无形状中?
鉴于两个case classes:
case class Foo(x: Int)
case class Bar(x: Int)
Run Code Online (Sandbox Code Playgroud)
用shapeless,我怎么能确定Foo,并Bar具有相同的"形",即Int :: HNil是HList?