1 ::列出foldLeft中的[Nothing] [英] 1 :: List[Nothing] in foldLeft
问题描述
如果:
scala> val l = List()// List()与List相同[Nothing]()
l:List [Nothing] = List()
scala> 1 :: l
res0:List [Int] = List(1)
或者:
scala> 1 :: List [Nothing]()
res6:List [Int] = List(1)
为什么然后这不起作用:
scala>列表(1,2,3)。 foldLeft(List())((acc,x)=> x :: acc)
我必须明确输入 List [Int]()
:
阶>列表(1,2,3)。 foldLeft(List [Int]())((acc,x)=> x :: acc)
res3:List [Int] = List(3,2,1)
?
尽管它在Haskell中有效,例如:
$ b $foldl(\acc x - > x:acc)[] [1,2,3]
操作:
$ c
解决方案让我们来看看scala的foldLeft签名:
列表[+ A] .foldLeft [B](z:B)(f:(B,A)⇒B):B
和haskell的签名:
foldl :: (b→a→b)→> b - > [a] - > b
它们几乎相同,但:
1)scala在[伪] curried参数列表之间有类型推断的问题,只是比较:
scala> def aaa [A](a:A)(b:A)= {}
aaa:[A](a:A)(b:A)单位
scala> aaa(null:任何)(5)
scala> aaa(5)(null:Any)
< console>:21:error:type mismatch;
找到:任何
都需要:Int
aaa(5)(null:Any)
^
所以scala可以从左到右选择更大的类型。 更重要的是,这只是[pseudo - ] curried函数:
scala> def aaa [T](a:T,b:T)= a
aaa:[T](a:T,b:T)T
scala> aaa(List(a),List(6.0))
res26:List [Any] = List(a)
scala> aaa(List(6.0),List(a))
res27:List [Any] = List(6.0)
这里scala不仅选择了更大的类型 - 它找到了一个共同的超类型
T
的s。所以,它试图在默认情况下选择更大的类型(如果它在左边部分),但是在一个参数列表中寻找一个常见的超类型。
注意:我是谈论[pseudo-] currying,作为具有多个参数列表的方法
(B)((B,A)=> B)B
仅在eta-expansion之后变为curried函数:foldLeft _
给出B => (B,A)=> 2)haskell使用
List的
Prelude>让f = foldl(\acc x - > x:acc)[]
:: [a] - > [a] //这里是多态函数
Prelude> f [1,2,3]
[3,2,1]
前奏> f [1,2,3]
[3,2,1]
在scala中你需要:
scala> (x,f)= x :: acc)
$ 3)最后,让我们重写
f:[T](x:列表[T])列表[T]
scala> f(List(1,2,3))
res3:List [Int] = List(3,2,1)
scala> f(List(1,2,3))
res3:List [String] = List(3,2,1)
foldLeft
,并将monoid的'add'和'identity'放在同一个参数列表中(避免与p.1分开推论):
pre $def foldLeft [T,U](l:List [T]) (身份:U,add:(U,T)=> U)= l.foldLeft(identity)(add)
并定义多态
add
scala> ; def add [A](x:List [A],y:A)= y :: x
add:[A](x:List [A],y:A)List [A]
所以您可以:
阶> foldLeft(List(1,2,3))(Nil,add)
$ p
res63:List [Int] = List(3,2,1)
$ b与以下比较:
scala> List(1,2,3).foldLeft(Nil)(add)
< console>:9:error:多态表达式不能实例化为预期类型;
found:[A,B](x:List [A],y:A)List [A]
required:(scala.collection.immutable.Nil.type,Int)=> scala.collection.immutable.Nil.type
List(1,2,3).foldLeft(Nil)(add)
^
不幸的是,scala不能推断lambda表达式的泛型类型,所以你不能:
阶> foldLeft(List(1,2,3))(Nil,(acc,x)=> x :: acc)
< console>:10:error:缺少参数类型
foldLeft(List (1,2,3))(Nil,(acc,x)=> x :: acc)
您无法:
scala> val a =(acc,x)=> x :: acc
< console>:7:错误:缺少参数类型
val a =(acc,x)=> x :: acc
^
<2>& 3)因为scala完全没有多态lambda 。无法推断A =>列表[A] =>从
(甚至(acc,x)=>的一个
(其中A是一个类型参数) x :: accA => A
fromval a =(a)=> a
),但Haskell可以:
Prelude> let lambda = \acc x - > x:acc
:: [a] - > a - > [a]
前奏>让f = foldl(lambda)[]
Prelude> f [1,2,3]
[3,2,1]
这里是在scala中定义了
add
泛型方法的eta-expansion:
阶>添加_
res2:(List [Nothing],Nothing)=> List [Nothing] =< function2>
If:
scala> val l = List() // List() same as List[Nothing]() l: List[Nothing] = List() scala> 1 :: l res0: List[Int] = List(1)
or:
scala> 1 :: List[Nothing]() res6: List[Int] = List(1)
Why then this does not work out:
scala> List(1,2,3). foldLeft( List() ) ((acc,x) => x :: acc)
So I have to type this explicitly
List[Int]()
:scala> List(1,2,3). foldLeft( List[Int]() ) ((acc,x) => x :: acc) res3: List[Int] = List(3, 2, 1)
?
Though it does in Haskell, for example:
foldl (\acc x -> x:acc) [] [1,2,3]
解决方案Let's look at scala's foldLeft signature:
List[+A].foldLeft[B](z: B)(f: (B, A) ⇒ B): B
and haskell's signature:
foldl :: (b -> a -> b) -> b -> [a] -> b
They pretty much same, but:
1) scala has problem with type inference between [pseudo-]curried parameter lists, just compare:
scala> def aaa[A](a: A)(b: A) = {} aaa: [A](a: A)(b: A)Unit scala> aaa(null: Any)(5) scala> aaa(5)(null: Any) <console>:21: error: type mismatch; found : Any required: Int aaa(5)(null: Any) ^
So scala can choose bigger type from left to right only.
More than that, this is a problem only for [pseudo-]curried functions:
scala> def aaa[T](a: T, b: T) = a aaa: [T](a: T, b: T)T scala> aaa(List("a"), List(6.0)) res26: List[Any] = List(a) scala> aaa(List(6.0), List("a")) res27: List[Any] = List(6.0)
Here scala had not only choosed a bigger type - it had found a common supertype of both
T
's. So, it's trying to choose bigger type (if it's in the left part) by default, but looking for a common supertype inside one parameter list.Note: I'm talking about [pseudo-] currying, as method with multiple parameter lists
(B)((B, A) => B)B
becoming curried function only after eta-expansion:foldLeft _
givesB => (B,A) => B
2) haskell uses "object" of
List
itself as function's parameter, which allows you to do even:Prelude> let f = foldl (\acc x -> x:acc) [] :: [a] -> [a] //here is the polymorphic function Prelude> f [1,2,3] [3,2,1] Prelude> f ["1","2","3"] ["3","2","1"]
In scala you need:
scala> def f[T](x: List[T]) = x.foldLeft(List[T]()) ((acc,x) => x :: acc) f: [T](x: List[T])List[T] scala> f(List(1,2,3)) res3: List[Int] = List(3, 2, 1) scala> f(List("1","2","3")) res3: List[String] = List(3, 2, 1)
3) Finally, let's rewrite
foldLeft
and place monoid's 'add' and 'identity' to the same parameter list (to avoid separate inference from p.1):def foldLeft[T, U](l: List[T])(identity: U, add: (U,T) => U) = l.foldLeft(identity)(add)
and define polymorphic
add
operation:scala> def add[A](x: List[A], y: A) = y :: x add: [A](x: List[A], y: A)List[A]
So you can:
scala> foldLeft(List(1,2,3))(Nil, add) res63: List[Int] = List(3, 2, 1)
in comparision with:
scala> List(1,2,3).foldLeft(Nil)(add) <console>:9: error: polymorphic expression cannot be instantiated to expected type; found : [A, B](x: List[A], y: A)List[A] required: (scala.collection.immutable.Nil.type, Int) => scala.collection.immutable.Nil.type List(1,2,3).foldLeft(Nil)(add) ^
Unfortunately, scala can't infer generic type for lambdas, so you can't:
scala> foldLeft(List(1,2,3))(Nil, (acc,x) => x :: acc) <console>:10: error: missing parameter type foldLeft(List(1,2,3))(Nil, (acc,x) => x :: acc)
as you can't:
scala> val a = (acc,x) => x :: acc <console>:7: error: missing parameter type val a = (acc,x) => x :: acc ^
2 & 3) Because scala has no polymorphic lambdas at all. Can't infer
A => List[A] => A
(where A is a type parameter) from(acc,x) => x :: acc
(evenA => A
fromval a = (a) => a
), but Haskell can:Prelude> let lambda = \acc x -> x:acc :: [a] -> a -> [a] Prelude> let f = foldl(lambda) [] Prelude> f [1,2,3] [3,2,1]
Here is an eta-expansion of perviously defined
add
generic method in scala:scala> add _ res2: (List[Nothing], Nothing) => List[Nothing] = <function2>
这篇关于1 ::列出foldLeft中的[Nothing]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!