2017-09-17 8 views
3
def meh[M[_], A](x: M[A]): M[A] = x 
meh((x: Int) => "") 

SI-2712(https://issues.scala-lang.org/browse/SI-2712)の後、修正型Aは右端の​​型パラメータに推論されます。 Function1 [Int、String]の私の例では、Stringです。型コンストラクタ推論の上位統一

左パラメータに推論させる方法は?

なぜこのアプローチが機能していないのですか?

class T[K,M]{} 

def inferToLeft[S[_,_],K,B](ot: S[K,B]):({type Op[T] = S[T,B]})#Op[K]= ot 

meh(inferToLeft(new T[Int,String])) 
それはまだStringに推測されています

の代わりのInt

+1

私は質問の最初の部分の答えを見つけることができたと思います:この問題を「修正」し、左から右、右から左の部分的な統一を許していた猫とスカラジにUnapplyクラスがありました。 "左から右への"ケースは非常にまれであるため、Unapplyはcatsライブラリから削除されました。 SI-2712は左から右への統合を許可していません。この目的のために、スカラズまたは子猫のプロジェクトのUnapplyクラスを使用する必要があります。 –

答えて

2

コンパイラは、(私は申し訳ありませんそのための理論的根拠を知らない)できるだけ早く安定した名前を持っていない種類を拡大することを好むので、あなたのタイプ戻りスポットのラムダは、mehへのコールの前に簡素化されています。良いニュースは、あなたがそれを一般化するためにあなたの利点に統一を使用することができるということです。

ここ
import scala.reflect.runtime._, universe._ 
import scala.language.higherKinds 

def checkUnification[F[_], A: TypeTag](fa: => F[A]) = s"${typeOf[A]}" 

implicit class InferToLeft[M[_, _], A, B](a: M[A, B]) { 
    def lefty: InferToLeft.U[M, B, A] = a 
} 

object InferToLeft { 
    type U[M[_, _], B, A] = M[A, B] 
} 

def e: Either[Int, String] = ??? 
def f: AnyRef => List[Int] = ??? 

assert(checkUnification(e) == "String") 
assert(checkUnification(e.lefty) == "Int") 
assert(checkUnification(f) == "scala.List[Int]") 
assert(checkUnification(f.lefty) == "AnyRef") 

あなたの引数が簡素化なしU[M, B, A]として渡されるので、タイプInferToLeft.Uは、統一Aを選んで作る、安定したパスで利用可能ですあなたの型コンストラクタの左引数です。