我在这个博客中看到了这个代码:Scala中的类型级编程:
// define the abstract types and bounds
trait Recurse {
type Next <: Recurse
// this is the recursive function definition
type X[R <: Recurse] <: Int
}
// implementation
trait RecurseA extends Recurse {
type Next = RecurseA
// this is the implementation
type X[R <: Recurse] = R#X[R#Next]
}
object Recurse {
// infinite loop
type C = RecurseA#X[RecurseA]
}
Run Code Online (Sandbox Code Playgroud)
#代码中有一个R#X[R#Next]我从未见过的运算符.由于难以搜索(被搜索引擎忽略),谁能告诉我它是什么意思?
在javascript中,我们可以这样做:
["a string", 10, {x : 1}, function() {}].push("another value");
Run Code Online (Sandbox Code Playgroud)
什么是Scala等价物?
List("a").contains(5)
Run Code Online (Sandbox Code Playgroud)
因为a Int永远不会包含在列表中String,所以这应该在编译时生成错误,但事实并非如此.
它浪费并默默地测试String列表中包含的每个内容的相等性5,这些内容永远不会成立(在Scala中"5"永远不等于5).
这被称为" '包含'问题 ".而一些人暗示,如果一个类型系统无法正确地输入这样的语义,那么为什么要经过强制执行类型的额外的努力.所以我认为这是一个需要解决的重要问题.
类型参数化B >: A的List.contains输入的任何类型的是该类型的超类型A(包含在列表中的元素的类型).
trait List[+A] {
def contains[B >: A](x: B): Boolean
}
Run Code Online (Sandbox Code Playgroud)
此类型参数化是必要的,因为+A声明列表在类型上是协变的A,因此A不能在逆变位置中使用,即作为输入参数的类型.协变列表(必须是不可变的)对于扩展比强制列表(可以是可变的)更强大.
A是String在上面的例子有问题,但Int不是的超类型String,所以发生了什么事?该隐含包容 Scala中,决定Any是两者的相互超String和Int.
Scala的创建者Martin Odersky 建议修复将限制输入类型B仅限于那些具有equals方法的类型Any.
trait List[+A] …Run Code Online (Sandbox Code Playgroud) 让我们假设我有一个具有两个类型参数的特征,例如
trait Qux[A, B]
Run Code Online (Sandbox Code Playgroud)
和另一个具有更高通道类型参数的特征,例如
trait Turkle[C[_]]
Run Code Online (Sandbox Code Playgroud)
我希望能够将一个固定值替换为其中一个类型参数Qux,以便它可以用于参数化Turkle.
这是一个示例(在Scala中没有意义的代码!):
trait Baz[A] extends Turkle[Qux[A, _]]
Run Code Online (Sandbox Code Playgroud)
任何人有任何想法如何实现这种效果?
我有两个对象,ObjectA和ObjectB,都有方法update().我想编写一个接受ObjectA或ObjectB(但没有其他类型)的函数.从概念上讲,这就是我要做的事情:
def doSomething[T <: ObjectA | T <: ObjectB](obj: T) = {
obj.update
}
Run Code Online (Sandbox Code Playgroud)
我意识到还有其他方法可以解决这个问题(例如,update()方法的结构类型,公共基类等)但我的问题是它可以在Scala中这样做,如果是这样,语法是什么?这叫什么?
我知道类型擦除使它们在运行时看起来相同,类型,所以:
class Bar {
def foo[A](xs: A*) { xs.foreach(println) }
def foo[A, B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)) }
}
Run Code Online (Sandbox Code Playgroud)
给出以下编译器错误:
<console>:7: error: double definition:
method foo:[A,B](xs: (A, B)*)Unit and
method foo:[A](xs: A*)Unit at line 6
have same type after erasure: (xs: Seq)Unit
def foo[A,B](xs: (A, B)*) { xs.foreach(x => println(x._1 + " - " + x._2)
) }
^
Run Code Online (Sandbox Code Playgroud)
但是有一种简单的方法可以写:
bar.foo(1, 2, 3)
bar.foo(1 -> 2, 3 -> 4)
Run Code Online (Sandbox Code Playgroud)
并让这些调用foo的不同重载版本,而不必明确命名它们:
bar.fooInts(1, 2, …Run Code Online (Sandbox Code Playgroud) 是否可以在Scala中执行以下操作:
class MyTest {
def foo[A <: String _or_ A <: Int](p:List[A]) = {}
}
Run Code Online (Sandbox Code Playgroud)
也就是说,类型A可以是String或Int.这可能吗?
(这里有类似的问题)
随着Ceylon 1.0的发布,一些人正在讨论联合类型的有用性.我想知道你如何简洁地编写以下代码:
String test(String | Integer x) {
if (x is String) {
return "found string";
} else if (x is Integer) {
return "found int";
}
return "why is this line needed?";
}
print(test("foo bar")); // generates 'timeout'... well, whatever
Run Code Online (Sandbox Code Playgroud)
......在斯卡拉?我的想法是这样的:
type | [+A, +B] = Either[A, B]
object is {
def unapply[A](or: Or[A]): Option[A] = or.toOption
object Or {
implicit def left[A](either: Either[A, Any]): Or[A] = new Or[A] {
def toOption = either.left.toOption
}
implicit def right[A](either: Either[Any, …Run Code Online (Sandbox Code Playgroud) 可以说类型参数T必须具有特定的超类型S_1:
class Test[T <: S_1]
Run Code Online (Sandbox Code Playgroud)
有没有办法说,一个类型参数必须至少有一个超类型的多个超类型备选方案?像(伪代码)的东西:
class Test[T <: S_1 || S_2]
Run Code Online (Sandbox Code Playgroud)
或者:这是不可能的,因为这样的结构毫无意义,并且会在代码中暗示设计错误?
我目前正在集思广益,研究在scala中进行显式错误处理的最佳方法.
理想的最终产品:
基本上,我想在steriods上检查异常.
忽略异常抛出,处理这种情况的典型方法是使用Either类型(或\/来自我正在使用的Scalaz),并将left侧面作为包含所有可能错误的ADT,如下所示:
sealed trait Error_parseAndValidate
case class ParseError(msg: String) extends Error_parseAndValidate
case class ValidateError(msg: String) extends Error_parseAndValidate
def parseAndValidate(str: String): Error_parseAndValidate \/ Int = {
// can return ParseError or ValidateError
}
Run Code Online (Sandbox Code Playgroud)
但是,如果函数调用嵌套多个级别,这将变得非常繁琐:
考虑具有以下调用堆栈的此DB示例
main- > getResultWithString- >parseAndValidate / fetchResultFromDB
// error type ADT containing expected errors in parseAndValidate
// similarly for other error_* traits
sealed trait Error_parseAndValidate
case class ParseError(msg: String) extends …Run Code Online (Sandbox Code Playgroud) scala ×10
types ×3
arrays ×1
contains ×1
covariance ×1
currying ×1
generics ×1
list ×1
macros ×1
overloading ×1
shapeless ×1
type-bounds ×1
type-erasure ×1
type-systems ×1