1

I have:

trait A[B[_]]

and I have:

trait Base {
    type AImpl <: ???
    def foo: AImpl
}

so that the classes extending Base would define A and implement methods and fields. ie:

trait BB[T]
trait AA extends A[BB]

trait Child extends Base {
  override type AImpl = AA
}

My problem is with declaring the abstract type AImpl. I tried:

type AImpl <: A[B[_]] forSome {type B[_]}

but I am getting the following compile error:

B[_] takes no type parameters, expected: one
type AImpl <: A[B[_],_] forSome {type B[_]}

What is the right way of declaring this abstract type?

1
  • this can hardly be what you want. to be specific, the chances are you also want to make AImpl higher kinded. Commented Feb 21, 2018 at 17:18

1 Answer 1

1

This code does what you are asking but I don't think you mean to do that:

trait A[B[_]]

trait Base {
  type AImpl <: A[B] forSome { type B[_] }
  def foo: AImpl
}

if you can be more specific I can probably pinpoint your problem and suggest another way of doing so.


As I previously insisted, there are many problems in your intention. It's very clear to me that you are trying to do something you are not supposed to.

To explain a couple issue, you first need to understand existential types. Here, you are quantifying AImpl with certain constraint:

type AImpl <: A[B] forSome { type B[_] }

This asks its realization to comply to such type. However, this type cannot possibly have any realization, because of

  1. B is hidden inside of existential type, therefore it's unknown outside;
  2. A is invariant, so it forces realization to be subtype of A[B] for that exact hidden B.

these two together forbids AImpl from realizing. The way to fix it is to turn A covariant:

trait A[+B[_]]

trait Base {
  type AImpl <: A[B] forSome { type B[_] }
  def foo: AImpl
}

trait BB[T]
trait AA extends A[BB]

object Child extends Base {
  override type AImpl = A[BB]

  def foo = ???
}

this code compiles with no problem.

However, again, I have to say existentially quantifying B is a fundamentally flawed idea, because in the given environment, there is no type safe way to recover B anymore, if you ever need it, not to mention higher kinded types in scala is insufficient and malformed.

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

8 Comments

thanks. your solution almost works but it still gives me errors. I have updated my expected usage. Basically, I want to have "type families".
@Mathsnoob this sample code compiled in my IDE. the chances are you need to turn on higher kinded types in compiler option. anyways, let me check what you want.
why you can't drop A[B[_],_]? it's clear that A here is of kind (*, *) -> *, which cannot possibly be correct. it's still unclear what you want from this aspect. also, existential type in scala is fundamentally broken, and in most occasion, it's not what you want. so what problem are you trying to solve?
sorry for the confusion. the above is a simplification of my code and I forgot to also change the error. You're right. the original error was: A[B[_]] forSome {type B[_]}. The error I am getting on your code is: Error:(11, 18) overriding type AImpl in trait Base with bounds <: A$A32.this.A[_[_] <: Any]; type AImpl has incompatible type override type AImpl = AA ^ here is a gist: gist.github.com/ShahOdin/4bde0c7844589fa7dfaf6a255dfd9a20
@Mathsnoob i've addressed that error from my update.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.