gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 01:21:52 25 4
gpt4 key购买 nike

shapeless 文档解释了如何使用多态函数来创建将一种容器中的对象映射到另一种容器的函数,但是当您想要从容器中解包时呢?

我有一个 HList 选项

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 将不会被找到。解决这个问题的最好方法是定义一个返回 Option 的智能 Some 构造函数:

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 都必须是采用单个类型参数的类型构造函数——例如选项 ~> 列表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——即,它是为您提供未包装类型的身份类型构造函数。

这个版本可以编译并返回一个有用类型的结果,但它仍然不是很安全,因为如果你用 None 的元素映射 hlist (在运行时),您将得到一个 NoSuchElementException。除了将 Option ~> Id 更改为 Some ~> Id,以某种方式提供默认值等之外,没有任何办法解决这个问题,所有这些都会改变操作非常显着。

关于scala - 使用多态函数从选项中提取对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39628022/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com