编辑:我将问题重新表述为更简单且更少域特定的问题:在下面的代码中,我想实现mplus函数,该函数结合了受特定字段存在约束的两个函数.结果函数应该受到两个字段的存在的约束.谢谢 !
import shapeless._, ops.record.Selector, record._, syntax.singleton._
def requiresIntervalKey[L <: HList](l: L)
(implicit sel: Selector.Aux[L, Witness.`"interval"`.T, Int]): Unit = {
println(sel(l))
}
def requiresPlatformField[L <: HList](l: L)
(implicit sel: Selector.Aux[L, Witness.`"platform"`.T, String]): Unit = {
println(sel(l))
}
def mplus = ??? // That is the function I'd like to implement. Eventually it will be the additive operator of a monoid
// needsBothFields: L <: HList -> (implicit) Selector.Aux[L, Witness.`"interval"`.T, Int] -> (implicit) Selector.Aux[L, Witness.`"platform"`.T, String] -> Unit
val needsBothField = mplus(requiresIntervalKey _, requiresIntervalKey _ )
// Usage
requiresIntervalKey(("interval" ->> "a string") :: HNil) // Shoudn't compile, value type is wrong
requiresIntervalKey(("wrongKey" ->> "a string") :: HNil) // Shoudn't compile, "interval" key not provided
requiresIntervalKey(("interval" ->> 42) :: HNil) // Compiles
requiresPlatformField(("platform" ->> "EU") :: HNil) // Compiles
needsBothFields(("interval" ->> 42) :: ("platform" ->> "EU") :: HNil) // Should compile
Run Code Online (Sandbox Code Playgroud)
//上一个问题版本
对于无形和类型级编程来说,我很难实现我的目标并获得清晰的理解.非常感谢您的帮助!
我基本上有几个函数如下所示:
trait PathGenerator[T] {
def apply(T): Set[Seq[String]]
}
val hourlyIntervalPathGenerator: PathGenerator[Interval] = ???
val constantGenerator: PathGenerator[String] = ???
// A Monoid[PathGenerator]
// an implicit class adding a '/' operator to PathGenerator
// Usage
val hourlyRegionPathGenerator = hourlyIntervalPathGenerator / constantGenerator
val paths = hourlyRegionPathGenerator(StaticIntervals.lastDay, "EU")
Run Code Online (Sandbox Code Playgroud)
现在,当将两个以上的生成器一起添加时,用户必须使用嵌套元组.此外,命名生成器参数对于生成解析器非常有用(例如:cmd-line.)
无形记录似乎非常合适,所以我继续实施以下非工作解决方案:https: //gist.github.com/amazari/911449b55270a5871d14
这个不可构建的代码和我无形的误解产生了几个问题:
L26: keys("interval")和L35: keys(constant))不会返回预期类型的值,即使提供了Witness和选择器也很困难.那么,记录是否是实现此用例的正确工具?代码段中未显示从PathPattern的记录形状/模板生成的命令行解析器.
我怎么能强制提供给生成器的记录(简单的或由几个组合产生的)在名称和类型方面具有完全正确的字段?
谢谢你的帮助!
编辑:这一系列问题和Travis Brown的答案非常相关:
这对于 Shapeless 来说是可能的,尽管不完全是您所要求的形式。这是一个简单的例子:
\n\nimport shapeless._, ops.record.Selector, record._, syntax.singleton._\n\nclass UseKey[K <: String, V, R](w: Witness.Aux[K])(f: V => R) extends Poly1 {\n implicit def onRecord[L <: HList](implicit\n sel: Selector.Aux[L, K, V]\n ): Case.Aux[L, R] = at[L](l => f(sel(l)))\n}\n\nclass Combine[P1 <: Poly1, P2 <: Poly1, R1, R2, R](\n p1: P1,\n p2: P2\n)(f: (R1, R2) => R) extends Poly1 {\n implicit def onRecord[L <: HList](implicit\n c1: p1.Case.Aux[L, R1],\n c2: p2.Case.Aux[L, R2]\n ): Case.Aux[L, Unit] = at[L](l => f(c1(l), c2(l)))\n}\n\nclass mplus[P1 <: Poly1, P2 <: Poly1](p1: P1, p2: P2)\n extends Combine(p1, p2)((_: Unit, _: Unit) => ())\nRun Code Online (Sandbox Code Playgroud)\n\n进而:
\n\nobject requiresIntervalKey extends UseKey(Witness("interval"))(\n (i: Int) => println(i)\n)\n\nobject requiresPlatformField extends UseKey(Witness("platform"))(\n (s: String) => println(s)\n)\n\nobject needsBothFields extends mplus(requiresIntervalKey, requiresPlatformField)\nRun Code Online (Sandbox Code Playgroud)\n\n(作为旁注,我猜你可以直接写UseKey("platform")在这里,但由于某种原因,捕获见证的隐式转换不起作用。幸运的Witness("platform")是,还不错。)
接下来展示它的工作原理:
\n\nscala> import test.illTyped\nimport test.illTyped\n\nscala> illTyped("""requiresIntervalKey("interval" ->> "a string" :: HNil)""")\n\nscala> illTyped("""requiresIntervalKey("wrongKey" ->> "a string" :: HNil)""")\n\nscala> requiresIntervalKey("interval" ->> 42 :: HNil)\n42\n\nscala> requiresPlatformField("platform" ->> "EU" :: HNil)\nEU\n\nscala> needsBothFields("interval" ->> 42 :: "platform" ->> "EU" :: HNil)\n42\nEU\nRun Code Online (Sandbox Code Playgroud)\n\n我们需要而不是常规的旧函数的原因Poly1是,我们无法收集组合普通函数时所需的不同证据\xe2\x80\x94,相反,我们需要多态函数值(Shapeless 提供为PolyN)。
还值得注意的是,这并不是真正的“幺半群”。类型的幺半群实例提供了一种操作,该操作采用该类型的两个值并返回另一个值。这里mplus有两个操作,每个操作都有自己的隐含要求,并为我们提供了另一个操作,它具有两者的组合要求。
| 归档时间: |
|
| 查看次数: |
283 次 |
| 最近记录: |