72

有人可以简单地向我解释 Shapeless 库的用途吗?

Scala 具有泛型和继承功能,所以我有点困惑 Shapeless 的用途。

也许一个用例来澄清事情会有所帮助。

4

3 回答 3

51

有点难以解释,因为 shapeless 具有广泛的特征;我可能会发现“用简单的术语解释变量的用途”更容易。您肯定想从功能概述开始。

从广义上讲,shapeless 是关于使用类型进行编程。在编译时做一些通常在运行时做的事情,精确跟踪列表中每个元素的类型,能够从元组转换为 HLists 到案例类,创建多态函数(相对于方法),等等

典型的使用场景如下:

  • 从某处读取一堆值到List
  • 将它的类型安全List转换为HList
  • HList使用多态函数映射它,例如规范化值
  • 将第三个元素(静态已知为 an Int)转换为 0 填充字符串
  • 使用 HList 中的值构造案例类

作为参考, anHList将具有精确的类型,例如Int :: String :: Boolean :: HNil(是的,这确实一种类型),其中所有内容都固定下来并且大小固定。因此,您要么需要在编译时确切地知道 HList 中的内容,要么需要类型安全的强制转换。

如果你采用tail这样的 HList 的 ,你会得到一个String :: Boolean :: HNil,并且编译时保证 this 的头部是一个String。在头部添加一个值同样会保留所有涉及的类型。

Shapeless 还带有Generic类型类,允许您在元组和案例类上使用 HList 操作。

我倾向于使用的其他功能是:

  • Coproducts,它允许您静态键入一个值,例如“a String, Doubleor Int, but nothing else”(很像Either,但不仅限于两种可能性)

  • Lenses,这简化了嵌套案例类的工作。

于 2014-02-12T21:03:54.067 回答
32

在您尝试使用类型并委托或打开类型之前,查看 anHList可能看起来令人费解。看看以下内容:

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

在运行时,这可能会抛出 a MatchError,因为我实际上并没有告诉你什么是类型fred。它可能是类型Fred

HList如果您未能捕获该列表的一种类型,您可以在编译时立即知道。在上面,如果我在myList = 1 :: 2 :: "3" :: fred :: HNil访问第三个元素时定义了它,它的类型将是String,这将在编译时知道。

正如@KevinWright 所说,除了Shapeless 之外,它还有更多功能,但它HList是该库的定义功能之一。

于 2014-02-12T21:24:53.657 回答
20

Shapeless 中的一切都有两个共同点:

首先,它不在 Scala 标准库中,但可以说应该在。因此,询问 Shapeless 的用途有点像询问 Scala 标准库的用途!这是为了一切。这是一个手提袋。

(但它不是一个完全随意的抓包,因为:)

其次,Shapeless 中的所有内容都在编译时提供了增强的检查和安全性。Shapeless 中没有任何东西(我能想到的?)实际上在运行时“做”任何事情。当你的代码被编译时,所有有趣的动作都会发生。目标始终是增加信心,即如果您的代码完全编译,它不会在运行时崩溃或做错事。(因此这个值得注意的俏皮话:https ://twitter.com/mergeconflict/status/304090286659866624 )

在https://stackoverflow.com/a/4443972/86485上有一个很好的介绍类型级编程的全部内容,以及更多资源的链接。

于 2014-02-13T20:55:11.943 回答