44

関数リテラルがあります

{case QualifiedType(preds, ty) =>
               t.ty = ty ;
               Some((emptyEqualityConstraintSet,preds)) }

エラーメッセージが表示される

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

SLS 8.5を調べましたが、説明が見つかりませんでした。

関数を自分で展開すると

{(qt : QualifiedType) =>
  qt match {case QualifiedType(preds, ty) =>
               t.ty = ty ;
               Some((emptyEqualityConstraintSet,preds)) }}

エラーはなくなります。

(a) なぜこれがエラーなのですか?

(b) どうすれば修正できますか?

: QualifiedTypeパターンと => の間に追加するという明らかな修正を試みましたが、これは構文エラーです。


私が気づいたことの 1 つは、コンテキストが違いを生むということです。関数リテラルを、期待されると宣言された関数の引数として使用すると、QualifiedType => Bエラーは発生しません。しかし、 を期待する関数の引数として使用するとA => B、エラーが発生します。ここで起こっていることは、型が QualifiedType のスーパータイプであるオブジェクトにパターンが適用される可能性があるため、関数が適用されないという保証がなければ、コンパイラは明らかな型を割り当てようとしないということです。 QualifiedType ではないもの。本当に私が望んでいるのは{QualifiedType( preds, ty) => ...} 、Haskell の\QualifiedType(preds,ty) -> ....

4

3 に答える 3

39

{ case X(x) => ... }は部分関数ですが、コンパイラはX. 通常、これは問題になりません。匿名関数を作成している場合、型はコンテキストから認識されるためです。ただし、タイプを提供する方法は次のとおりです。

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

お気づきかもしれませんが、ここで関数リテラルやパターン マッチングを使用しても意味がありません。あなたの場合、通常の方法が必要なだけのようです:

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

ただし、その可変状態を削除するにはリファクタリングする必要があります。

于 2012-10-13T03:06:26.293 に答える
7

私たちの残りの人のためのSLSの引用は次のとおりです。

そのような式の予想される型は、部分的に定義する必要があります。scala.Functionk[S1, . . . , Sk, R]いくつかの k > 0 の場合、または の いずれかである必要がありますscala.PartialFunction[S1, R]。ここで、引数の型は S1 です。. . 、Sk は完全に決定されている必要がありますが、結果の型 R は決定されていない可能性があります。

そうでなければ、あなたはあなたの質問に答えました。

于 2012-10-13T02:32:33.593 に答える
4

これが、関数リテラルを使用したかった理由であり、型を 2 回繰り返す必要がありませんでした。オプションに一致するすべてのコードを除外するために、独自の制御構造を構築しようとしていました。オーバーヘッドが大きすぎる場合、制御構造は役に立ちません。これが私がやりたかったことです

//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)) } ) 

スイッチ制御構造は正常にコンパイルされますが、SLS では A がある場合は「明確な型」が必要であると指示されているため、使用法によってエラーが発生しました。これは、この種の関数リテラル (「ケース」を含む種類) が、引数が正当なものである可能性がある部分関数を対象としているためです。関数リテラルに int を使用すると主張できますが、それは型エラーではなく、単にすべてのパターンが失敗するという問題です。したがって、コンパイラは、「展開された関数リテラル」のパラメーターにどのタイプを意図するかを知るために、「トップダウン」情報が必要です。つまり、次の X に何を入力するか

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

コンパイラがスイッチの型を使用して部分関数を意図していないことを確認し、A を QualifiedType と統合できなかったのはなぜだろうか。しかし、そうではありません。

とにかく、それはコンパイルされません。ただし、 A を Any に置き換えると、エラーが解消されます。次のコードは実際にコンパイルされます。私が失うのは、いくつかの型チェックです。

//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)) } ) 

(a) 上記の switch の定義を改善できるかどうか、および (b) 必要な機能を実行するライブラリ関数が既に存在するかどうかを知りたいと思います。


ルイージのコメントの後に追加

これが最終的なコードです。はい、褶曲(カタモルフィズム)だと思います。

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

ルイージのおかげです。

于 2012-10-13T19:52:05.670 に答える