使用多态函数从选项中提取对象

2024-01-13

无形状文档解释了如何使用多态函数来创建将一种容器中的对象映射到另一种容器中的函数,但是当您想从容器中解压东西时该怎么办?

我有一个选项列表

val options = Some(1) :: Some("A") :: Some(3.5) :: HNil

我想要一个多态函数,可以提取每个选项的内容。

// This is incorrect:
object uuu extends (Option ~> Any) {
  def apply[T](l:Option[T]):T = {
    l.get
  }
}

如果这个函数是正确的,我想要以下行为:

options.map(uuu) // I want: 1 :: "A" :: 3.5 :: HNil

我该如何纠正这个问题,以便我的多态函数真正起作用?


这里有几个问题。首先是你的 hlist 的静态类型有Some在其中而不是Option, 所以Mapper你需要证明的证据uuu可以映射到options不会被发现。解决这个问题最好的方法是定义一个智能的Some返回一个构造函数Option:

def some[A](a: A): Option[A] = Some(a)

val options = some(1) :: some("A") :: some(3.5) :: HNil

您还可以在原始内容中添加类型注释options,或改变uuu跟...共事Some代替Option(这会更安全,但对于您想要做的任何事情来说可能不太有用)。

现在你的代码编译并执行某物,但只是因为有点奇怪的事实Any在 Scala 中是种类多态的。一般来说,当你有F ~> G, both F and G必须是采用单个类型参数的类型构造函数,例如Option ~> List. Any不接受类型参数,但它可以工作,因为 Scala 语言有一个奇怪的事实(即Any, 和...一起Nothing,是种类多态的,并且适合您需要类型、带有一个参数的类型构造函数、带有十几个参数的类型构造函数等的任何槽。)

所以它编译了,但它毫无用处,因为它返回一个Any :: Any :: Any :: HNil。您可以通过替换来修复此问题Any在自然变换中shapeless.Id:

import shapeless._, shapeless.poly.~>

def some[A](a: A): Option[A] = Some(a)

val options = some(1) :: some("A") :: some(3.5) :: HNil

object uuu extends (Option ~> Id) {
  def apply[T](l: Option[T]): T = l.get
}

options.map(uuu)

Id定义为type Id[+T] = T—即,它是为您提供未包装类型的标识类型构造函数。

这个版本既编译又给你返回一个有用的类型结果,但它仍然不是真正安全,因为如果你映射一个hlist的元素是None(在运行时),你会得到一个NoSuchElementException。除了改变之外,没有什么办法可以解决这个问题Option ~> Id to Some ~> Id,以某种方式提供默认值等,所有这些都极大地改变了操作的性质。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用多态函数从选项中提取对象 的相关文章

随机推荐