首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用多态函数从选项中提取对象

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

Stack Overflow用户
提问于 2016-09-21 23:28:50
回答 1查看 139关注 0票数 3

非形状文档解释了如何使用多态函数来生成将一种容器中的对象映射到另一种容器中的函数,但是当您想从它们的容器中解压东西时呢?

我有一个HList的选项

代码语言:javascript
运行
复制
val options = Some(1) :: Some("A") :: Some(3.5) :: HNil

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

代码语言:javascript
运行
复制
// This is incorrect:
object uuu extends (Option ~> Any) {
  def apply[T](l:Option[T]):T = {
    l.get
  }
}

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

代码语言:javascript
运行
复制
options.map(uuu) // I want: 1 :: "A" :: 3.5 :: HNil

我如何纠正这一点,使我的多态函数实际工作?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-09-22 10:48:00

这里有几个问题。首先,您的hlist的静态类型中有Some而不是Option,因此找不到您需要证明uuu可以映射到options之上的Mapper证据。解决这个问题的最好方法是定义一个返回一个Some的智能Option构造函数。

代码语言:javascript
运行
复制
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时,FG都必须是接受单个类型参数的类型构造函数,例如Option ~> ListAny不接受类型参数,但是它可以工作,因为Scala语言的这个奇怪的事实( AnyNothing都是多态的,并且适合您需要一个类型、一个带一个参数的类型构造函数、一个带十几个参数的类型构造函数等等)。

所以它编译了,但是它非常无用,因为它返回一个Any :: Any :: Any :: HNil。您可以通过将自然转换中的Any替换为shapeless.Id来修复这个问题。

代码语言:javascript
运行
复制
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-i.e.,它是身份类型构造函数,为您提供了未包装的类型。

这个版本同时编译并返回一个有用的输入结果,但它仍然不太安全,因为如果您在hlist上映射None元素(在运行时),您将得到一个NoSuchElementException。除了将Option ~> Id更改为Some ~> Id、以某种方式提供默认值等之外,没有任何方法可以解决这些问题,所有这些都极大地改变了操作的性质。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/39628022

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档