На ваш первый вопрос «Что за тип object com.test.M
и чем он отличается от com.test.M.type
?» До сих пор не дан ответ. Я не нашел его документированным в спецификации, но кажется, что тип object M
является внутренним типом, представляющим класс, который неявно создается при определении объекта M
. Конечно, M
является единственным экземпляром этого класса, поэтому можно ожидать, что тип object M
будет эквивалентен M.type
, но компилятор, очевидно, не видит его таким образом.
Проблема, с которой вы столкнулись, как объяснил @ retronym , заключается в том, что синглтонный тип M.type
не выводится для параметра типа при вызове метода make
. Это по той же причине, по которой String
выводится вместо v.type
в следующем сеансе:
scala> val v = "asdf"
v: java.lang.String = asdf
scala> identity(v)
res0: java.lang.String = asdf
, где identity
определяется как
def identity[T](v: T) = v