2017-03-07 2 views
0

Scala Set/Map은 유선 유형 추론을 초래할 수 있습니다. 일부 CanBuildFrom와 "기본값"는 immutable.Map 유형을 초래할 수에 대해 예를 들어스칼라에서지도에 대한 유형 추론

, REPL

$ val m2 = Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty) 
> scala.collection.immutable.Map[String,scala.collection.immutable.Map[_ <: String, Int]] = Map(foo -> Map(bar -> 6), baz -> Map()) 

에서 나는 알고있다.

그러나 내부가 ...Map[String, Int]이 아닌 ...Map[_ <: String, Int] 인 이유는 무엇입니까?

관찰 : 예상대로 아래에 정의

m1 유추된다. 명시 적 유형의 귀속으로

$ val m1 = Map("foo" -> Map("bar" -> 5)) 
> scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Int]] = Map(foo -> Map(bar -> 5)) 

는 모두 변환 할 수 있습니다 "제대로"(나는이 CanBuildFrom 때문이라고 생각) :

val _m1: Map[String, Map[String, Int]] = Map("foo" -> Map("bar" -> 5)) 
val _m2: Map[String, Map[String, Int]] = Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty) 

나는 몇 가지 기능 라이브러리를 사용할 때 내가 예를 들어, 이후이 신경, cats, 두 피연산자가 같은 유형인지 확인해야하며 을 알고 싶습니다. 형식 오름차순을 사용해야합니다. 예를 들어,

import cats.Semigroup 
import cats.implicits._ 
m1 ++ m2 // works 
m1 |+| m2 // error 
// found : scala.collection.immutable.Map[String,scala.collection.immutable.Map[_ <: String, Int]] 
// required: scala.collection.immutable.Map[String,scala.collection.immutable.Map[String,Int]] 

답변

2

여기에 직장에서 더 CanBuildFrom의, Map 키 만 불변성이 없습니다.

당신은 쓸 때 :

Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty) 

컴파일러는이 유형을 추론하려고하고 일을 그렇게 그것은 일반적인 Map("bar" -> 6)의 종류와 Map.empty을 알아낼 필요가 고마웠다 최소 상한을 . 이 유형의 매개 변수를 제공하지 않는 경우

Map.emptyMap[Nothing, Nothing], 그래서 컴파일러는 Map[String, Int]Map[Nothing, Nothing]의 상한선 최소한의 계산과는 실존 유형Map[_ <: String, Int]와 함께 제공됩니다. 이는 Map인데, 첫 번째 유형 매개 변수 인 불변 식이기 때문입니다. 컴파일러는 Map.empty의 유형 매개 변수를 추정하는 데 사용되는 힌트를 추가하고 있기 때문에 당신이 유형의 주석을 추가 할 때 작동

(A Map[Nothing, Int]Map[String, Int]하지 않습니다). 힌트가 없으면 행복하게 Map[Nothing, Nothing]을 대신 사용합니다. 이것은 형식 유추에 약간의 결함이 있습니까? 아마도. 나는 항상 안전을 위해서 CollectionType.empty의 유형 매개 변수를 제공하는 것을 선호합니다.

val m2 = Map("foo" -> Map("bar" -> 6), "baz" -> Map.empty[String, Int]) 
+0

'Map [String, Int]'및'Map [Nothing, Nothing]'이 실존 유형'Map [_ <: String, Int]'인 이유를 알고 싶습니까? –

+1

다른 맵을 Map [Int, Int] 또는 무언가가 아닌 다른 것으로 만들면 컴파일러가 실재 타입으로 LUB을 생성하는 방법을 더 쉽게 볼 수 있습니다. 당신은'_> : SomeOtherType'을 가진 문자열을 얻습니다.'SomeOtherType'은 컴파일러가 유용한 무언가를 얻으려고하는 호환되지 않는 타입입니다.'Nothing' with Nothing'은 단지'String'이고, 컴파일러는'String with Nothing'을'String'으로 대체합니다. –

+0

하지만 다른 점은 적어도 방향은 반대로되어 있습니까? –