假设我们有以下类和一些值(在Scala中):
class A[T](val x: T)
class B[T](x: T, val y: T) extends A[T](x)
val x1 = new A("test")
val x2 = new B(1,2)
val x3 = new B("foo","bar")
val x4 = new A(1)
Run Code Online (Sandbox Code Playgroud)
此外,我们定义以下多态函数值(使用无形):
object f extends (A ~> Option) {
def apply[T](s: A[T]) = Some(s.x)
}
Run Code Online (Sandbox Code Playgroud)
现在我们可以致电:
f(x1); f(x2); f(x3); f(x4)
Run Code Online (Sandbox Code Playgroud)
哪一切都成功了(应该恕我直言).然而:
val list = x1 :: x2 :: x3 :: x4 :: HNil
list.map(f)
// could not find implicit value for parameter mapper:
// shapeless.Mapper[f.type,shapeless.::[A[String],shapeless.::[
// B[Int],shapeless.::[B[String],shapeless.::[A[Int],shapeless.HNil]]]]]
Run Code Online (Sandbox Code Playgroud)
我期待的地方: …
我对无形特征概述中显示的示例感到困惑.
object size extends Poly1 {
implicit def caseInt = at[Int](x => 1)
implicit def caseString = at[String](_.length)
implicit def caseTuple[T, U]
(implicit st : Case.Aux[T, Int], su : Case.Aux[U, Int]) =
at[(T, U)](t => size(t._1)+size(t._2))
}
scala> size(((23, "foo"), 13))
res7: Int = 5
Run Code Online (Sandbox Code Playgroud)
提前谢谢了
我正在尝试学习Shapeless,我想定义一个monoid,它将无形记录的实例加在一起.请注意,我使用的是algebird monoids(不是scalaz),但我确信它们非常相似.以下是我希望能够做到的一个例子:
val result = Monoid.sum(
('a ->> 1) :: ('b ->> 1) :: HNil,
('a ->> 4) :: ('b ->> 3) :: HNil,
('a ->> 2) :: ('b ->> 6) :: HNil)
// result should be: ('a ->> 7) :: ('b ->> 10) :: HNil
Run Code Online (Sandbox Code Playgroud)
我想出了如何为HList编写monoid实例,如下所示:
implicit val HNilGroup: Group[HNil] = new ConstantGroup[HNil](HNil)
implicit val HNilMonoid: Monoid[HNil] = HNilGroup
class HListMonoid[H, T <: HList](implicit hmon: Monoid[H], tmon: Monoid[T]) extends Monoid[::[H, T]] {
def zero = hmon.zero :: tmon.zero
def …Run Code Online (Sandbox Code Playgroud) 我想我需要一个受限制的HList,它的所有元素都是某种类型的子类型.LUBConstraint似乎是我想要的,事实上它确实限制了这样一个HList 的构造 - 但是我看不出如何再次获取证据,所以我可以映射(实际上,遍历,因为它需要是monadic)在HList上并调用每个元素上的方法(存在于LUB类型中).
另外,我希望从遍历操作得到的HList的类型与输入HList的类型完全相同.
用例是一种功能性的"监听器列表" - HList的所有元素都是"监听器",必须通知"事件",接受或拒绝它们,并返回更新的"内部状态"的新版本.如果这就是我所需要的,那么我可以使用普通的不可变Scala集合.但我也希望直接键入单个元素而不使用asInstanceOf- 因此尝试使用HList的动机.
我正在使用Shapeless并使用以下方法计算两个HLists之间的差异:
def diff[H <: HList](lst1: H, lst2:H):List[String] = (lst1, lst2) match {
case (HNil, HNil) => List()
case (h1::t1, h2::t2) if h1 != h2 => s"$h1 -> $h2" :: diff(t1, t2)
case (h1::t1, h2::t2) => diff(t1, t2)
case _ => throw new RuntimeException("something went very wrong")
}
Run Code Online (Sandbox Code Playgroud)
由于该方法的两个参数都采用了H,我希望不同类型的HLists不能在这里编译.例如:
diff("a" :: HNil, 1 :: 2 :: HNil)
Run Code Online (Sandbox Code Playgroud)
不应该编译,但确实如此,它会产生运行时错误:java.lang.RuntimeException: something went very wrong.我可以对类型参数做些什么来使这个方法只接受相同类型的两个边?
我正在观察一个非常奇怪的类型错误shapeless.everywhere.考虑下面的菊石脚本加载正常load.module:
load.ivy("com.chuusai" %% "shapeless" % "2.3.0")
@
import shapeless._
import poly._
final case class Person(name: Person.Name, age: Person.Age)
object Person {
final case class Name(value: String) extends AnyVal
final case class Age(value: Int) extends AnyVal
}
def happyBirthday(person: Person, howManyYearsPast: Int): Person = {
object incAge extends ->((age: Int) => age + howManyYearsPast)
// THE MAGIC VAL
val oldPerson = everywhere(incAge)(person)
oldPerson
}
val john = Person(Person.Name("John Doe"), Person.Age(42))
val oldJohn = happyBirthday(john, 30)
Run Code Online (Sandbox Code Playgroud)
现在,如果我尝试MAGIC …
HList按类型过滤很容易:
val hlist = 1 :: 2 :: "3" :: true :: false :: HNil
hlist.filter[Int]
Run Code Online (Sandbox Code Playgroud)
但是如何制作我的自定义类型过滤器?我想要那样的smth:例如我得到了一些函数的列表:
def function1(s: String) = s.toInt
def function2(s: String) = s.toDouble
def function3(i: Int) = i.toDouble
val hflist = function1 _ :: function3 _ :: function2 _ :: HNil
hflist customFilter[String] //> function1 _ :: function2 _ :: HNil
Run Code Online (Sandbox Code Playgroud)
因此,在使用此过滤器之后,String将构造从类型到其他类型的函数列表.
我有一个想法,为此使用地图,但它没有成功.
版
有关我的评论的更多信息:
我试图在地图上测试这个想法:
所以,如果我有一些列表(让我们使用hlist&hflist):
object allFunction extends Poly1 {
implicit def default[T, M] =
at[T => …Run Code Online (Sandbox Code Playgroud) 假设我有Show[T]Scalaz中的特征:https://github.com/scalaz/scalaz/blob/scalaz-seven/core/src/main/scala/scalaz/Show.scala#L9
我也有一个无形的HList,可能看起来像"1" :: 2 :: 3L :: HNil.
有没有办法找到Show每个元素的实例并应用shows这样我最终"1" :: "2" :: "3L" :: HNil?
如果任何元素的类型Show在范围内没有隐式实例,我会想要编译错误.
我认为,如果我建立一个HList对的Show情况下,我应该能够用zipApply得到HList我想要的,但我不知道是否有一种方式来获得具有斯卡拉推断HList的Show实例,而不是我建起来的手.
我想编写一个以Nat为参数的函数,并且如果此nat不能被3整除,则返回此nat.
例如 :
def myFunction[N <: Nat](n :N)(implicit ev: /* what do I put here that say not divible by 3 ? */): N = n
Run Code Online (Sandbox Code Playgroud)
要做到这一点,我必须写一些说"N不能被_3整除"的东西,或者"Mod.Aux [N,_3,_0]是空类型"
我怎么能在无形的情况下做到这一点?
鉴于以下关于亚扪人:
@ import $ivy.`io.circe::circe-core:0.9.0`
@ import $ivy.`io.circe::circe-generic:0.9.0`
@ import $ivy.`com.chuusai::shapeless:2.3.3`
@ import shapeless.tag
import shapeless.tag
@ trait Foo
defined trait Foo
@ import io.circe._, io.circe.generic.semiauto._
import io.circe._, io.circe.generic.semiauto._
@ import shapeless.tag.@@
import shapeless.tag.@@
Run Code Online (Sandbox Code Playgroud)
然后,我尝试定义通用标记类型解码器:
@ implicit def taggedTypeDecoder[A, B](implicit ev: Decoder[A]): Decoder[A @@ B] =
ev.map(tag[B][A](_))
defined function taggedTypeDecoder
Run Code Online (Sandbox Code Playgroud)
它在明确拼写时有效String @@ Foo:
@ val x: String @@ Foo = tag[Foo][String]("foo")
x: String @@ Foo = "foo"
@ implicitly[Decoder[String @@ Foo]]
res10: Decoder[String @@ Foo] = io.circe.Decoder$$anon$21@2b17bb37
Run Code Online (Sandbox Code Playgroud)
但是,在定义类型别名时:
@ …Run Code Online (Sandbox Code Playgroud)