【发布时间】:2014-03-11 10:37:57
【问题描述】:
有人可以简单地向我解释一下 Shapeless 库的用途吗?
Scala 具有泛型和继承功能,所以我有点困惑 Shapeless 的用途。
也许一个用例来澄清事情会有所帮助。
【问题讨论】:
有人可以简单地向我解释一下 Shapeless 库的用途吗?
Scala 具有泛型和继承功能,所以我有点困惑 Shapeless 的用途。
也许一个用例来澄清事情会有所帮助。
【问题讨论】:
有点难以解释,因为 shapeless 具有广泛的特征;我可能会发现“用简单的术语解释变量的用途”更容易。你肯定想从feature overview开始。
广义上讲,shapeless 是关于使用类型进行编程。在编译时做一些通常在运行时做的事情,精确跟踪列表中每个元素的类型,能够从元组转换为 HLists 到案例类,创建多态函数(相对于方法),等等
典型的使用场景如下:
List
List 的类型安全转换为HList
HList,例如标准化值Int)转换为 0 填充字符串作为参考,HList 将具有精确的类型,例如 Int :: String :: Boolean :: HNil(是的,这确实是单一类型),其中所有内容都固定下来并且大小固定。因此,您要么需要在编译时确切地知道 HList 中的内容,要么需要类型安全的强制转换。
如果你获取这样一个 HList 的tail,你会得到一个String :: Boolean :: HNil,并且编译时保证它的头部将是一个String。在头部添加一个值同样会保留所有涉及的类型。
Shapeless 还带有 Generic 类型类,允许您对元组和案例类使用 HList 操作。
我倾向于使用的其他功能是:
Coproducts,它允许您静态键入一个值,例如“String、Double 或 Int,但仅此而已”(很像 Either,但不仅限于两种可能性)
Lenses,简化了嵌套案例类的使用。
【讨论】:
在您尝试使用类型并委托或打开类型之前,查看HList 可能看起来令人费解。看看以下内容:
val myList = 1 :: 2 :: "3" :: fred :: Nil
这里的myList 是什么类型?如果您要检查它,您会发现它的类型为List[Any]。这不是很有帮助。如果我尝试在它上面使用以下PartialFunction[Any] 到map,则更有帮助:
myList.map{
case x: Int => x
case x: String => Int.parseInt(x)
}
在运行时,这可能会抛出MatchError,因为我实际上并没有告诉你fred 是什么类型。它可以是Fred 类型。
使用HList,您可以在编译时知道您是否未能捕获该列表的其中一种类型。在上面,如果我在访问第三个元素时定义了myList = 1 :: 2 :: "3" :: fred :: HNil,它的类型将是String,这将在编译时知道。
正如@KevinWright 所说,除了Shapeless 之外,它还有更多功能,但HList 是该库的定义功能之一。
【讨论】:
Shapeless 中的一切都有两个共同点:
首先,它不在 Scala 标准库中,但可以说应该在。因此,询问 Shapeless 的用途有点像询问 Scala 标准库的用途!它适用于一切。这是一个手提包。
(但它不是一个完全随意的抓包,因为:)
其次,Shapeless 中的所有内容都在编译时提供了增强的检查和安全性。 Shapeless 中没有任何东西(我能想到的?)实际上在运行时“做”任何事情。当你的代码被编译时,所有有趣的动作都会发生。目标始终是增加信心,即如果您的代码完全编译,它不会在运行时崩溃或做错事。 (因此这个值得注意的俏皮话:https://twitter.com/mergeconflict/status/304090286659866624)
在https://stackoverflow.com/a/4443972/86485 上有一个很好的关于类型级编程的介绍以及更多资源的链接。
【讨论】: