The argument types of an anonymous function must be fully known. (SLS 8.5)

拥有回忆 提交于 2019-11-28 06:17:31
som-snytt

Here's the SLS quote, for the rest of us:

The expected type of such an expression must in part be defined. It must be either scala.Functionk[S1, . . . , Sk, R] for some k > 0, or scala.PartialFunction[S1, R], where the argument type(s) S1, . . . , Sk must be fully determined, but the result type R may be undetermined.

Otherwise, you answered your question.

{ 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 of X. 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:

case class Foo(x: Int)

// via annotation
val f: Foo => Int = { case Foo(x) => x }

// use pattern matching
val f = (_: Foo) match { case Foo(x) => x }

// or more normally, write as a method
def f(a: Foo) = a match { case Foo(x) => x }
def f(a: Foo) = a.x

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:

def whatever(qt: QualifiedType) = {
  t.ty = qt.ty
  Some((emptyEqualityConstraintSet, qt.preds)) 
}

although you should refactor to remove that mutable state.

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

//This is the control construct definition
def switch[A,B]( x : Option[A], noneFun : =>B, someFun : A=>B) = x match {
    case None => noneFun 
    case Some(y) => someFun(y) }

//And this is an example of using it.
def foobar( qt : Option[QualifiedType]  ) = 
    switch( qt, {reportError("SNAFU");None},
            {case QualifiedType(preds, ty) =>
               Some((emptyEqualityConstraintSet,preds)) } ) 

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

{(x : X) => x match {case Some(QualifiedType(preds, ty)) =>
               Some((emptyEqualityConstraintSet,preds)) } }

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.

//This is the control construct definition
def switch[A,B]( x : Option[A], noneFun : =>B, someFun : A=>B) = x match {
    case None => noneFun 
    case Some(y) => someFun(y) }

//And this is an example of using it.
def foobar( qt : Option[QualifiedType]  ) = 
    switch( qt, {reportError("SNAFU");None},
            {case QualifiedType(preds, ty) =>
               Some((emptyEqualityConstraintSet,preds)) } ) 

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).

def switch[A,B]( x : Option[A])(noneFun : =>B, someFun : A=>B) = x match {
    case None => noneFun 
    case Some(y) => someFun(y) }

def foobar( qt : Option[QualifiedType]  ) : Option[(EqualityConstraintSet, TypeRelationSet)] =
    switch( qt )({reportError("SNAFU");None},
            {case QualifiedType(preds, ty) =>
               Some((emptyEqualityConstraintSet,preds)) } ) 

Thanks to Luigi.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!