加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 记录为参数,组成

发布时间:2020-12-16 18:34:15 所属栏目:安全 来源:网络整理
导读:编辑:我将问题重新表述为更简单,更少域名的问题: 在下面的代码中,我想实现mplus函数,该函数结合了由特定字段的存在约束的两个函数.结果函数应该受到两个字段的存在的约束. 谢谢 ! import shapeless._,ops.record.Selector,record._,syntax.singleton._def
编辑:我将问题重新表述为更简单,更少域名的问题:
在下面的代码中,我想实现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,Int] -> (implicit) Selector.Aux[L,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

//上一个问题版本

对于无形和类型级编程来说,我很难实现我的目标并获得清晰的理解.非常感谢您的帮助!

我基本上有几个函数如下所示:

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")

现在,当将两个以上的生成器一起添加时,用户必须使用嵌套元组.此外,命名生成器参数对于生成解析器非常有用(例如:cmd-line.)

无形记录似乎很合适,所以我继续实施以下非工作解决方案:
https://gist.github.com/amazari/911449b55270a5871d14

这个不可构建的代码和我无形的误解产生了几个问题:

>从记录中获取字段的值(L26:键(“间隔”)和L35:键(常量))不会返回预期类型的??值,即使提供了Witness和选择器也很困难.
>在编写其中两个时,我无法提取正确的子记录类型以传递给基础生成器(L52-53.)
> L69:由于我不明白的原因,所提供的记录与所需的类型不符.

那么,记录是否是实现此用例的正确工具?代码段中未显示从PathPattern的记录形状/模板生成的命令行解析器.

我怎么能强制提供给生成器的记录(简单的或由几个组合产生的)在名称和类型方面具有完全正确的字段?

谢谢你的帮助!

编辑:这一系列问题和Travis Brown的答案非常相关:

Passing a Shapeless Extensible Record to a Function
Passing a Shapeless Extensible Record to a Function (continued)
Passing a shapeless extensible record to a function (never ending story?

解决方法

这对Shapeless来说很有可能,尽管不是你想要的形式.这是一个简单的例子:

import shapeless._,syntax.singleton._

class UseKey[K <: String,V,R](w: Witness.Aux[K])(f: V => R) extends Poly1 {
  implicit def onRecord[L <: HList](implicit
    sel: Selector.Aux[L,K,V]
  ): Case.Aux[L,R] = at[L](l => f(sel(l)))
}

class Combine[P1 <: Poly1,P2 <: Poly1,R1,R2,R](
  p1: P1,p2: P2
)(f: (R1,R2) => R) extends Poly1 {
  implicit def onRecord[L <: HList](implicit
    c1: p1.Case.Aux[L,R1],c2: p2.Case.Aux[L,R2]
  ): Case.Aux[L,Unit] = at[L](l => f(c1(l),c2(l)))
}

class mplus[P1 <: Poly1,P2 <: Poly1](p1: P1,p2: P2)
  extends Combine(p1,p2)((_: Unit,_: Unit) => ())

然后:

object requiresIntervalKey extends UseKey(Witness("interval"))(
  (i: Int) => println(i)
)

object requiresPlatformField extends UseKey(Witness("platform"))(
  (s: String) => println(s)
)

object needsBothFields extends mplus(requiresIntervalKey,requiresPlatformField)

(作为旁注,我猜想你可以在这里写下UseKey(“平台”),但由于某种原因,捕获见证的隐式转换不起作用.幸运的是,Witness(“平台”)也不行坏.)

接下来显示它的工作原理:

scala> import test.illTyped
import test.illTyped

scala> illTyped("""requiresIntervalKey("interval" ->> "a string" :: HNil)""")

scala> illTyped("""requiresIntervalKey("wrongKey" ->> "a string" :: HNil)""")

scala> requiresIntervalKey("interval" ->> 42 :: HNil)
42

scala> requiresPlatformField("platform" ->> "EU" :: HNil)
EU

scala> needsBothFields("interval" ->> 42 :: "platform" ->> "EU" :: HNil)
42
EU

我们需要Poly1而不是常规旧函数的原因是我们无法在组合普通函数时收集我们需要的不同证据 – 而是我们需要多态函数值(Shapeless提供为PolyN).

值得注意的是,这并非真正的“幺半群”.类型的monoid实例提供了一个操作,该操作接受该类型的两个值并返回另一个值.这里的mplus有两个操作,每个操作都有自己的隐含要求,并给我们另一个操作,它具有两者的组合要求.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读