6

I always believed that type aliases always expand to their original type if necessary. But, here is a troublemaker

def a[P](a: Option[P]) = {
    type Res = List[P] // result type alias
    Nil: Res // Replace this line with Nil: List[P] to clear the error
}
def b[V](v: V) = a(Some(v)): List[V] 

it fails with (scastie)

error: type mismatch;
found   : Res (which expands to)  List[P]
required: List[V]

You see that a converts Option[P] => List[P] and, since b supplies Some[V], a converts Option[V] => List[V] when b calls it. But, compiler says that result is incompatible with List[V]. How is this possible? The error goes away (scastie) if you replace Nil: Res with Nil: List[P] in the a. You need to eliminate the type alias to get rid of the error. This means that the type alias is the culprit.

Little Alien
  • 1
  • 8
  • 22
  • 1
    Even if it's a compiler bug, it's weird and confusing to declare a type alias inside a method and use it to infer it's return type. – Michael Zajac Jun 27 '16 at 03:39
  • @m-z I just used it in [argument parsing recurion](http://stackoverflow.com/questions/38037089). Tell it is wrong and you know much better way. Actually, this is a programming style promoted by Oderki's Corusera course. They taught you that if you do not do foldLeft, you do a recursion. Recursion is the workhorse that can do everything if no special means to iterate the design space provisioned. The recursion means that you have a facade function, which accepts calls from users but the actual implemenation is done by `internal` recursive function. – Little Alien Jun 27 '16 at 13:19
  • That is, the basic functional pattern is `def facade(args)={def worker(iteration, accumulator: ResType):ResType = if (done) acc else {.recursion.} ; worker(starting args)}.` As you see, `acc` of the worker matches the resulting type and you are forced to declare the worker result type in Scala. That is, you need to specify your result type twice when coding the facade. Please downvote to display that following DRY it is wrong in this most basic FP pattern and save us from bad programming practices. Say that worker must be declared outside. Say that type inferece from inside is a bad smell. – Little Alien Jun 27 '16 at 13:26

1 Answers1

0

I'm almost certain this is a compiler bug. Type aliases in Scala are supposed to automatically expand, and it looks like in this case the type of a is inferred as [P](Option[P]) => Res, instead of [P](Option[P]) => List[P]. And since Res is in an inner scope, the compiler can't find it to infer the type of b correctly.

Others
  • 2,876
  • 2
  • 30
  • 52