有人能用简单的语言向我解释一下Shapeless库的用途吗?
Scala具有泛型和继承功能,所以我对Shapeless的用途有点困惑.
也许一个用例来澄清事情会有所帮助.
Kev*_*ght 47
这有点难以解释,因为无形具有广泛的功能; 我可能会发现更容易"用简单的术语解释变量的用途".您肯定希望从功能概述开始.
从广义上讲,无形是关于类型编程.在编译时做一些事情,通常在运行时完成,保持精确跟踪列表中每个元素的类型,能够从元组转换为HLists到案例类,创建多态函数(而不是方法),等等
典型的使用场景将类似于:
ListList成HListHList使用例如使值正常化的多态函数映射Int)转换为0填充字符串作为参考,一个HList将有一个精确的类型,如Int :: String :: Boolean :: HNil(是的,这确实是一个单一类型的)的一切是牵制和大小是固定的.因此,您需要在编译时确切知道将要进入HList的内容,或者您需要类型安全的强制转换.
如果你使用tail这样一个HList,你会得到String :: Boolean :: HNil一个编译时保证,这将是一个String.将值添加到头部将同样保留所涉及的所有类型.
Shapeless还附带了Generic类型类,允许您对元组和案例类使用HList操作.
我倾向于使用的其他功能是:
Coproducts,这让你静态类型的值作为例如"一个String,Double或者Int,但没有别的"(很像Either,但不局限于只有两个可能性)
Lenses,简化了嵌套案例类的使用.
whe*_*ies 32
在HList尝试使用类型和委托或切换类型之前,查看一个看起来令人困惑的东西.看看以下内容:
val myList = 1 :: 2 :: "3" :: fred :: Nil
Run Code Online (Sandbox Code Playgroud)
这是什么类型的myList?如果你要检查它,你会发现它是类型的List[Any].这不是很有帮助.更有帮助的是,如果我尝试使用以下内容PartialFunction[Any]来map覆盖它:
myList.map{
case x: Int => x
case x: String => Int.parseInt(x)
}
Run Code Online (Sandbox Code Playgroud)
在运行时,这可能会抛出一个,MatchError因为我实际上并没有告诉你什么类型fred.它可能是类型Fred.
随着HList你就可以知道正确在编译的时候,如果你没有捕捉类型列表中的一种.在上面,如果我在myList = 1 :: 2 :: "3" :: fred :: HNil访问第3个元素时已经定义了它的类型,那么String这将在编译时知道.
正如@KevinWright所说,除了Shapeless之外,它还有更多,但它HList是该库的定义功能之一.
Set*_*sue 20
Shapeless中的所有东西都有两个共同点:
首先,它不在Scala标准库中,但可以说应该是.因此,询问Shapeless的用途有点像用Scala标准库来询问!它适用于一切.这是一个抓包.
(但它不是一个完全随意的抓包,因为:)
其次,Shapeless中的所有内容都可以在编译时提供更高的检查和安全性.Shapeless中没有什么(我能想到的?)在运行时实际上"做"了什么.编译代码时会发生所有有趣的操作.目标始终是增加信心,如果您的代码完全编译,它将不会崩溃或在运行时做错事.(因此这个值得注意的讽刺:https://twitter.com/mergeconflict/status/304090286659866624)
通过/sf/answers/311078071/,可以很好地介绍什么类型级编程,以及更多资源的链接.