I have a function literal
{case QualifiedType(preds, ty) =>
t.ty = ty ;
Some((emptyEqualityConstraintSet,preds)) }
Which results in an error message
missing parameter type for expanded function The argument types of an anonymous function
must be fully known. (SLS 8.5) Expected type was:
? => Option[(Typer.this.EqualityConstraintSet, Typer.this.TypeRelationSet)]
I looked in SLS 8.5, but didn't find an explanation.
If I expand the function myself to
{(qt : QualifiedType) =>
qt match {case QualifiedType(preds, ty) =>
t.ty = ty ;
Some((emptyEqualityConstraintSet,preds)) }}
the error goes away.
(a) Why is this an error?
(b) What can I do to fix it?
I tried the obvious fix, which was to add : QualifiedType
between the pattern and the =>, but this is a syntax error.
One thing I noticed is that the context makes a difference. If I use the function literal as an argument to a function declared as expecting a QualifiedType => B
, there is no error. But if I use it as an argument to a function expecting an A => B
, there is an error. I expect that what is going on here is that, as the pattern could conceivably be applied to an object whose type is a supertype of QualifiedType, the compiler is not willing to assign the obvious type without assurance that the function won't be applied to anything that isn't a QualifiedType. Really what I'd like is to be able to write {QualifiedType( preds, ty) => ...}
and have it mean the same thing as Haskell's \QualifiedType(preds,ty) -> ...
.
Here's the SLS quote, for the rest of us:
Otherwise, you answered your question.
Here is why I wanted to use a function literal and didn't like having to repeat the type twice. I was trying to build my own control construct to factor out all the option matching code. If there is too much overhead, then the control construct doesn't help any. Here is what I wanted to do
The switch control construct compiles fine, but the usage caused an error because the SLS says that where I have an A, I should have a "definite type". That's because this kind of function literal (the kind with "case") is intended for partial functions where the argument could be legitimately any thing at all. I could argue my function literal with an int and that would not be a type error, but merely a matter of all the patterns failing. So the compiler needs some "top down" information to know what type I intend for the parameter of the "expanded function literal", i.e. what to put for X in the following
I wonder why the compiler could't use the type of switch to see that I don't intend a partial function and then unify A with QualifiedType. But it doesn't.
Anyway it doesn't compile. But replacing A with Any eliminates the error. The following code actually compiles. What I lose is some type checking.
I'd be interested to know (a) if the above definition of switch can be improved, and (b) if there is already a library function that does what I want.
Added after Luigi's Comment
Here is the final code. Yes, I think it is a fold (catamorphism).
Thanks to Luigi.
{ case X(x) => ... }
is a partial function, but the compiler still doesn't know what your input type is, except that it's a supertype ofX
. Normally this isn't a problem because if you're writing an anonymous function, the type is known from the context. But here is how you can provide the type:As you've probably noticed, using function literals / pattern matching here is pretty pointless. It seems in your case you just need a regular method:
although you should refactor to remove that mutable state.