我正在学习函数式编程,并且我试图理解协方差和逆变概念。我现在的问题是:我真的不知道什么时候应该对一般类型应用协方差和逆变。在具体的例子中,是的,我可以确定。但总的来说,我不知道哪种一般规则。
例如,这里有一些我研究过的规则:
在学习这个概念时我所知道的一些语言也使用这些惯例。例如: in 关键字用于协方差(在Scala中为+)和 out 关键字用于逆变(在Scala中为 - )。 Point(1)很容易理解。但在第(2)点,我看到异常:
methodA(Iterator<A>)
A应该是协方差methodA(Comparator<A>)
A应该是逆转。所以这里的例外情况是:虽然两个案例都使用泛型类型作为输入,但一个应该是协方差,而另一个应该是逆变。我的问题是:在设计课程时,我们是否有任何一般规则来决定协方差/逆变。
由于
答案 0 :(得分:2)
协方差和逆变就像是算术中数字的符号,当你在另一个中嵌入一个方差的位置时,组成是不同的。
比较
1] +(+a) = +a
2] -(+a) = -a
3] +(-a) = -a
4] -(-a) = +a
和
trait +[+A] { def make(): A } // Produces an A
trait -[-A] { def break(a: A) } // Consumes an A
1]
// Produces an A after one indirection: x.makeMake().make()
trait ++[+A] { def makeMake(): +[A] }
+[+[A]] = +[A]
2]
// Consumes an A through one indirection: x.breakMake(new +[A] { override def make() = a })
trait -+[-A] { def breakMake(m: +[A]) }
-[+[A]] = -[A]
3]
// Consumes an A after one indirection: x.makeBreak().break(a)
trait +-[-A] { def makeBreak(): -[A] }
+[-[A]] = -[A]
4]
// Produces an A through one indirection
// Slightly harder to see than the others
// x.breakBreak(new -[A] { override def break(a: A) = {
// you have access to an A here, so it's like it produced an A for you
// }})
trait --[+A] { def breakBreak(b: -[A]) }
-[-[A]] = +[A]
所以当你有
时def method(iter: Iterator[A])
整个方法参数处于逆变位置,A
位于Iterator
内的协变位置,但是-[+[A]] = -[A]
,所以A
实际上是-A
在此签名内的逆变位置,该类需要说A
。这是有道理的,外部用户正在传递一堆def method(comp: Comparator[A])
s,所以它应该是逆变的。
同样,在
中A
整个方法参数处于逆变位置,而Comparator
位于-[-[A]] = +[A]
内的逆变位置,因此您将它们组成A
并看到A
真的处于一个协变的位置。这也是有道理的。当您将Comparator
传递到A
时,外部用户可以控制它的作用,因此有点像将import csv
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait as wait
csvrows = []
def get_css_sel(selector):
posts = browser.find_elements_by_css_selector(selector)
for post in posts:
print(post.text)
csvrows.append(post.text)
browser = webdriver.Chrome(executable_path=r'//Users/Pranavtadepalli/Downloads/chromedriver')
browser.get("https://icostats.com")
wait(browser, 20).until(EC.presence_of_element_located((By.CSS_SELECTOR, "#app > div > div.container-0-16 > div.table-0-20 > div.tbody-0-21 > div:nth-child(2) > div:nth-child(8)")))
get_css_sel("#app > div > div.container-0-16 > div.table-0-20 > div.tableheader-0-50") #fetch header of table
get_css_sel("#app > div > div.container-0-16 > div.table-0-20 > div.tbody-0-21 > div") #fetch rows of table
new=[",".join(elem.split("\n")) for elem in csvrows]
newfile=open("csvfile.csv",'r')
newfile1=open("csvfile.csv",'w')
newstuff=newfile.read()
for elem in new:
newfile1.write(elem+'\n')
newfile1.close()
newfile.close()
返回给他们。