3

Ok, so I have this wonderfully simple setup:

trait Sys[S <: Sys[S]] trait Elem[S <: Sys[S]] trait AttrElem[S <: Sys[S]] { type E <: Elem[S] def attributes: Any def element: E } 

And a factory:

object Factory { def apply[S <: Sys[S], E1 <: Elem[S]]( elem: E1): AttrElem[S] { type E = E1 } = new Impl(elem) private class Impl[S <: Sys[S], E1 <: Elem[S]](val element: E1) extends AttrElem[S] { type E = E1 def attributes = 1234 } } 

Now in practice the f*** Scala type inference breaks down:

def test[S <: Sys[S]](elem: Elem[S]): Unit = { Factory(elem) } <console>:62: error: inferred type arguments [Nothing,Elem[S]] do not conform to method apply's type parameter bounds [S <: Sys[S],E1 <: Elem[S]] Factory(elem) ^ 

So my next attempt is existential types:

object Factory { def apply[S <: Sys[S], E1[~] <: Elem[~] forSome { type ~ <: Sys[~] }]( elem: E1[S]): AttrElem[S] { type E = E1[S] } = new Impl(elem) private class Impl[S <: Sys[S], E1[~] <: Elem[~] forSome { type ~ <: Sys[~] }]( val element: E1[S]) extends AttrElem[S] { type E = E1[S] def attributes = 1234 } } 

This gives me this following lovely message:

<console>:62: error: inferred kinds of the type arguments (S,E1[S]) do not conform to the expected kinds of the type parameters (type S,type E1) in class Impl. E1[S]'s type parameters do not match type E1's expected parameters: type E1 has one type parameter, but type E1 (in class Impl) has one elem: E1[S]): AttrElem[S] { type E = E1[S] } = new Impl(elem) ^ 

"type E1 has one type parameter, but type E1 has one" -- huh?


Question: How can I define the factory's apply method to infer the types?

4
  • Is f*** an abbreviation for f-bounded polymorphic? Commented Apr 24, 2014 at 17:36
  • 2
    It's a type formalism called System F*** (triple-star) Commented Apr 24, 2014 at 17:39
  • Can you describe what are you trying to achieve in "human words". Too hard for me to infer the meaning of Sys/Elem/AttrElem. Commented Apr 24, 2014 at 17:40
  • I want to be able to write Factory(elem) when elem is fully known, a sub-type of Elem[S]. Without having to type Factory[S, SomeSubtypeOfElem[S]](elem). In other words, I want to use the advertised feature of type-inference Commented Apr 24, 2014 at 17:42

1 Answer 1

3

The following "redundancy" seems to satisfy the compiler:

def apply[S <: Sys[S], E1 <: Elem[S]](elem: E1 with Elem[S]): AttrElem[S] { type E = E1 } = ... 

That is, adding with Elem[S]. It looks like a needless deficiency of the Scala compiler to not infer S from E1 <: Elem[S] where Elem is invariant in S.

Or am I missing a crucial bit?

Sign up to request clarification or add additional context in comments.

1 Comment

Here is another instance of the same problem: gist.github.com/ScrapCodes/10713689

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.