在我阅读时会出现几个问题.3.3.2从Joshua的Scala深度捕获类型约束.摘自本书的例子:
scala> def peek[C, A](col: C)(implicit ev: C <:< Traversable[A]) = (col.head, col)
peek: [C, A](col: C)(implicit ev: <:<[C,Traversable[A]])(A, C)
scala> peek(List(1, 2, 3))
res9: (Int, List[Int]) = (1,List(1, 2, 3))
Run Code Online (Sandbox Code Playgroud)
通过第一个参数列表C
发现它似乎很简单List[Int]
.如何<:<
通过方差强制类型约束在本书中进行了解释.但我不太明白这有多大帮助A
.
我的理解是,从第一个参数列表,scala发现C: List[Int]
,然后它寻找implicit ev: <:<[List[Int], Traversable[A]]
.目前A
仍然未知.它"拉动"两个暗示conforms[List[Int]]
并conforms[Traversable[A]]
匹配ev
.在任一情况下,以满足方差,List[Int] <: Traversable[A]
必须被满足,这导致这一发现A
是Int
.
它是否像我在这里描述的那样工作?特别是关于如何/何时A
推断.
我一般都了解什么类型的擦除以及为什么我们会遇到未经检查的警告.但是,我不明白为什么在以下情况下只发出一个未经检查的警告:
class A[K] {
def receive: PartialFunction[Any, Unit] = {
case ds: List[Double] => // unchecked warning
println("* List[Double]")
case kx: Vector[K] => // no unchecked warning
println("* Vector[K]")
}
}
object TestApp extends App {
val a = new A[Int]
a.receive(List("bar"))
a.receive(Vector("foo"))
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,两个接收呼叫都匹配案例条款.编译器确实对第一个子句发出警告:
警告:类型模式中的非变量类型参数Double [Double]未选中,因为它已被擦除消除.
我知道TypeTag [T]可以用来实现更好的类型安全性.但我关注的是为什么没有为第二个案件条款发出未经检查的警告.据我所知,类型参数K也被删除,并根据Java Generics FAQ
当编译器找到目标类型为参数化类型或类型参数的强制类型转换时,也会报告"未选中"警告
所以我想知道为什么不存在未经检查的警告?
我正在使用动态编程解决Haskell中的背包问题.我的第一次尝试是建立一个二维表.但是当输入很大时(例如100*3190802表),内存容易被炸毁.
知道任何给定的行i
只依赖于行(i - 1)
,我改为编写一个函数,希望利用尾递归:
import Data.Vector (Vector, (!))
import qualified Data.Vector as V
-- n items, k capacity, vs values, ws weights
ans:: Int -> Int -> Vector Int -> Vector Int -> Int
ans n k vs ws =
let row = initRow k vs ws
in row ! k
initRow :: Int -> Vector Int -> Vector Int -> Vector Int
initRow k vs ws = itbl 1 $ V.replicate (k + 1) 0 …
Run Code Online (Sandbox Code Playgroud) 我对Joshua Suareth的书Scala中的"5.1.3隐式解决方案"中的描述感到困惑,第100页:
Scala对象不能包含implicits的伴随对象.因此,必须从外部作用域提供与该对象类型的隐式作用域所需的对象类型相关的隐含.这是一个例子:
scala> object Foo {
| object Bar { override def toString = "Bar" }
| implicit def b : Bar.type = Bar
|}
defined module Foo
scala> implicitly[Foo.Bar.type]
res1: Foo.Bar.type = Bar
Run Code Online (Sandbox Code Playgroud)
但是我在REPL中隐藏了对象Bar:
scala> object Foo {
| implicit object Bar {
| override def toString = "isBar" }
| }
defined module Foo
scala> implicitly[Foo.Bar.type]
res0: Foo.Bar.type = isBar
Run Code Online (Sandbox Code Playgroud)
似乎它不需要在外部范围中定义隐式.或者我认为约书亚的意思完全错了?
我碰巧发现不允许在特征中使用抽象的私有字段,也就是说,
trait A1 {
//private val a: Int // Not allowed
protected val b: Int // OK
}
Run Code Online (Sandbox Code Playgroud)
如果私有字段是构造函数参数,那么对抽象类做这样的事似乎是可以的,也就是说,
abstract class A2 (private val i: Int) // OK
Run Code Online (Sandbox Code Playgroud)
所以我猜一个特征没有构造函数参数,因此没有办法初始化它们,因此不允许使用抽象的私有字段.
如果它们是"受保护的",则子类可以使用预先初始化的字段初始化它们.此方法允许子类查看这些字段.
如果我只想初始化它们并在之后隐藏它们,如下例所示,该怎么办?
object holding {
trait trick {
protected val seed: Int // Can't be private
final def magic: Int = seed + 123
}
trait new_trick extends trick {
def new_magic: Int = magic + 456
def the_seed: Int = seed // [1]
}
def play: new_trick = new { …
Run Code Online (Sandbox Code Playgroud) 在实现可排序的数据结构时,我正在考虑做这样的事情:
trait MaxHeap[T <: Ordering[T]] {
def insert(e: T): Unit
...
}
Run Code Online (Sandbox Code Playgroud)
但这对MaxHeap [Int]等类型不起作用.在标准集合库中,集合的元素类型T不受限制.相反,为需要将T转换为Ordering [T]的方法提供了隐式,例如
trait Seq[+A] extends ... {
// it's Ordering[B], not Ordering[A], but the idea is the same.
def max[B >: A](implicit cmp: Ordering[B]): A
}
Run Code Online (Sandbox Code Playgroud)
我的问题是,如果我的类/特性中有很多方法涉及比较,有没有办法指定类/特征的元素类型是可比较的,这样我就不需要声明这些方法的含义?
我正在通过阅读 ScalaCheck 的代码来学习 scala,发现许多组合器都以suchThat
. 然而,在很多情况下,这样的做法看起来并不是很有必要。我想知道为什么它们要这样设计。以下是GitHub上的一些摘录:
Example 1.
/** Picks a random value from a list */
def oneOf[T](xs: Seq[T]): Gen[T] =
choose(0, xs.size-1).map(xs(_)).suchThat(xs.contains)
Run Code Online (Sandbox Code Playgroud)
map
从 xs 中选择一个元素,因此xs.contains
看起来是多余的。
--
Example 2.
def containerOfN[C[_],T](n: Int, g: Gen[T])
(implicit evb: Buildable[T,C], evt: C[T] => Traversable[T]): Gen[C[T]] =
sequence[C,T](Traversable.fill(n)(g)) suchThat { c =>
c.size == n && c.forall(g.sieveCopy)
}
Run Code Online (Sandbox Code Playgroud)
c.size == n
既然成功sequence
返回的长度为 n ,为什么需要这样做呢?
--
Example 3.
/** Generates a string of alpha characters */ …
Run Code Online (Sandbox Code Playgroud)