有人可以向我解释一下Shapeless库的用途吗?

时间:2014-02-12 20:44:52

标签: scala shapeless

有人能用简单的语言向我解释一下Shapeless库的用途吗?

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

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

3 个答案:

答案 0 :(得分:47)

有点难以解释,因为无形具有广泛的功能;我可能会发现更容易“用简单的术语解释变量的用途”。你肯定想从feature overview开始。

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

典型的使用场景如下:

  • 从一个地方读取一堆值到List
  • List
  • 执行HList的类型安全演员
  • 使用多态函数映射HList,例如标准化值
  • 将第3个元素(静态地称为Int)转换为0填充字符串
  • 使用来自HList
  • 的值构造案例类

作为参考,HList将具有精确类型,例如Int :: String :: Boolean :: HNil(是的,真的 是单一类型),其中所有内容都固定下来并且大小合适是固定的。因此,您需要在编译时确切了解将要进入HList的内容,或者您​​需要类型安全的强制转换。

如果您使用此类HList的tail,则会获得String :: Boolean :: HNil,并且编译时保证其头部为String。将值添加到头部将同样保留所涉及的所有类型。

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

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

  • Coproducts,允许您静态输入值,例如“StringDoubleInt,但没有别的”(很像Either,但不仅限于两种可能性)

  • Lenses,简化了嵌套案例类的使用。

答案 1 :(得分:32)

在尝试使用类型,委托或切换类型之前,查看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,如果您未能捕获该列表的某种类型,则可以在编译时知道。在上面,如果我在访问第3个元素时已经定义了myList = 1 :: 2 :: "3" :: fred :: HNil,那么它的类型将是String,这将在编译时知道。

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

答案 2 :(得分:20)

Shapeless中的所有东西都有两个共同点:

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

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

其次,Shapeless中的所有内容都在编译时提供了更多的检查和安全 。 Shapeless中没有什么(我能想到的?)在运行时实际上“做”了什么。编译代码时会发生所有有趣的操作。目标始终是增加信心,如果您的代码完全编译,它将不会崩溃或在运行时做错事。 (因此这个值得注意的讽刺:https://twitter.com/mergeconflict/status/304090286659866624

https://stackoverflow.com/a/4443972/86485处有一个很好的介绍什么类型级编程,以及更多资源的链接。