(ãããã°)Scalaã«ããé«éåå¤æ° - Higher-kind Generics
ããã¤ã¤ã¼ã¼ã¼ã¼ã¼ããï¼ï¼ï¼ã
ã¨æ°åããå ¥ããã¨ããã§ãä»æ¥ã¯Scalaã®ã³ã¬ã¯ã·ã§ã³ã©ã¤ãã©ãªã§å¤ç¨ããã¦ãããHigher kind genericsã«ã¤ãã¦è»½ã解説ãããã¨æããã¤ã¤ã¼ã¼ã¼ã¼ã¼ããï¼ï¼ï¼
Higher-kind Generics(type constructor parameter)ã£ã¦?
ã¾ãã¶ã£ã¡ãã@kmizu ã解説ãã¦ããã¦ãã®ã§ã³ã¬èªãã§ãããã°ããã§ãã
ScalaのHigher-kind Genericsについて - Togetter
ããããã°æè¿Javaã§ãid:Nagiseã«ãããããªè©±ãããã¾ãããã
Javaによる高階型変数の実装 - プログラマーの脳みそ
Java による高階型変数と Scala とジェネリクス - Togetter
è¦ã¯ãåãã©ã¡ã¼ã¿ãåãåãã©ã¡ã¼ã¿(?)ã使ãããã£ã¦è©±ã
trait AttrHelper[+Holder[X]]
ã¨ãã£ãã¨ãã«ãHolderã£ã¦ã®ã¯åãã©ã¡ã¼ã¿ã§ãããã¤ã¯æ´ã«Xã¨ããåãã©ã¡ã¼ã¿ãã¨ããªããããã¨ããç¨ã«å®ç¾©ã§ãããã ãªãã
ã¡ãªã¿ã«Higher-kind Genericsã£ã¦ã®ã¯æ°´å³¶ãããå½åããååã§ãã¨ã ããã£ãã¼ã«ããã¨ããè¨èªä»æ§æ¸ã§ã¯"type constructor parameter"ã¨ããããã§ãã
"3.3.3 TypeConstructors"ã¨"4.4 Type Parameters"ãChangeLogã®"Changes in Version 2.5 (02-May-2007) Type constructor polymorphism"ããããè¦ãã¨ããã§ãããã
åã³ã³ã¹ãã©ã¯ã¿ãåãã©ã¡ã¼ã¿ã«åãä¾
è«ããã³ã¼ããä¾ãè¦ã¾ãã
// åã³ã³ã¹ãã©ã¯ã¿ type IntMap[A] = scala.collection.immutable.Map[Int, A] type StringMap[A] = scala.collection.immutable.Map[String, A] // ããåã®Mapã«proxyããtrait trait MapProxy[A,B, ReprMap[B] <: Map[A,B]] { val underlying:ReprMap[B] }
IntMap, StringMapã®ãµãã¤ã®åãå®ç¾©ãã¾ãããã©ã¡ãããAã¨ããåãã©ã¡ã¼ã¿ãåã£ã¦Map[Int, A]ã¨ãMap[String, A]ã¨ããã"å"ãè¿ãåã³ã³ã¹ãã©ã¯ã¿ã§ãã
ã§ããã®åã³ã³ã¹ãã©ã¯ã¿ãåãã©ã¡ã¼ã¿ReprMapã§åããMapProxyã¨ããtraitãå®ç¾©ãã¾ããã
ããã¤ã¯ãMapã®Keyã®åAãå¤ã®åBã¨ãProxyããMapã®åãè¿ãåã³ã³ã¹ãã©ã¯ã¿ReprMapãåãã©ã¡ã¼ã¿ã§ãããã¾ããunderlying ã¯ãProxyãã対象ã¨ãªãå®éã®Mapåã®å¤æ°ã§ãã
ãã®traitã使ãã¯ã©ã¹ã¯ããããªé¢¨ã«æ¸ãã¾ãã以ä¸ã¯ãStringåã®Keyããã¤Mapã¸proxyããã¯ã©ã¹ã¨ãIntåã®Keyãæã¤Mapã¸proxyããã¯ã©ã¹ã§ãã
class StringMapProxy[A](elems:(String, A)*) extends MapProxy[String, A, StringMap]{ val underlying:StringMap[A] = Map(elems:_*) def apply(key:String):A = underlying(key) } class IntMapProxy[A](elems:(Int, A)*) extends MapProxy[Int, A, IntMap]{ val underlying:IntMap[A] = Map(elems:_*) def apply(key:Int):A = underlying(key) }
å®éã«ä½¿ã£ã¦ã¿ã¾ãã
scala> val ssm = new StringMapProxy("foo"->"bar","hoge"->"fuga") ssm: StringMapProxy[java.lang.String] = StringMapProxy@199ec67 scala> ssm.underlying res9: StringMap[java.lang.String] = Map(foo -> bar, hoge -> fuga) scala> ssm("foo") res10: java.lang.String = bar scala> val sim = new StringMapProxy("foo"->1,"hoge"-> 2) sim: StringMapProxy[Int] = StringMapProxy@741bb804 scala> sim.underlying res11: StringMap[Int] = Map(foo -> 1, hoge -> 2) scala> val ibm = new IntMapProxy( 1 -> true, 2 -> false) ibm: IntMapProxy[Boolean] = IntMapProxy@785850e3 scala> ibm.underlying res12: IntMap[Boolean] = Map(1 -> true, 2 -> false) scala> ibm(1) res13: Boolean = true
StringMapProxy, IntMapProxyã¨ãã«ãproxyããMapã®åãåãã©ã¡ã¼ã¿ReprMapã§ä¸ããåã«ãªã£ã¦ãããã¨ããããã¨æãã¾ãã
scala.collectionããã±ã¼ã¸ã§ã®å©ç¨ä¾
scala.collectionããã±ã¼ã¸ã§ã®å©ç¨ä¾ãè¦ã¦ã¾ãã
以ä¸ã¯ãGenericCompanionã®å®ç¾©ã§ããããã¤ã¯ãåã«å¿ããBuilderãè¿ãããã®ã³ã³ãããªã³ã§ãCanBuildFromã¨ããåã«åããã¦ããæãã«implicit conversionããã2.8ã®ã³ã¬ã¯ã·ã§ã³ã©ã¤ãã©ãªã®ãã¢ã!ã¨ãªãæ½è±¡ã¯ã©ã¹ã§ãã
// CCã¯åXãåã£ã¦Traversable[X]以ä¸ã®åãè¿ãåã³ã³ã¹ãã©ã¯ã¿ abstract class GenericCompanion[+CC[X] <: Traversable[X]] // Traversableãçæããæ½è±¡ã¯ã©ã¹ // GenericCompanionãç¶æ¿ãã¦ãã abstract class TraversableFactory[CC[X] <: Traversable[X] with GenericTraversableTemplate[X, CC]] extends GenericCompanion[CC] // å®éã®Traversableã®å®ç¾©ãããã§CCã¯Traversableã«ãªã£ã¦ã object Traversable extends TraversableFactory[Traversable] { implicit def canBuildFrom[A]: CanBuildFrom[Coll, A, Traversable[A]] = new GenericCanBuildFrom[A] def newBuilder[A]: Builder[A, Traversable[A]] = new mutable.ListBuffer }
å®è·µçãªä¾:ç¹å®ã®åã®Iterableã¸Proxyããã¯ã©ã¹
ã¾ãã³ã¼ãã¨å©ç¨ä¾è¦ã¦ãã ãããIterableãproxyãã¤ã¤ãmapãfilterããã¨ãã«ãTraversableã¨ããããªãèªåã®åãè¿ãããã«ããããã®traitã§ãã
import scala.collection.{Iterable, IterableLike} trait TypedIterableProxy[A, Repr<: Iterable[A]] extends Iterable[A] with IterableLike[A, Repr]{ import scala.collection.generic.CanBuildFrom import scala.collection.mutable.{ListBuffer, Builder} val self:Iterable[A] def newTo(from:Iterable[A]):Repr def iterator = self.iterator override def newBuilder:Builder[A, Repr] = new ListBuffer[A] mapResult {x => newTo(x) } implicit def canBuildFrom: CanBuildFrom[Repr, A, Repr] = new CanBuildFrom[Repr, A, Repr] { def apply(from: Repr):Builder[A, Repr] = newBuilder def apply() = newBuilder } }
// ç¹å®ã®åã®Iterableã¸Proxyããã¯ã©ã¹ class StringItrableProxy(v:String*) extends Iterable[String] with TypedIterableProxy[String, StringItrableProxy] { val self= v.toIterable def newTo(from:Iterable[String]) = new StringItrableProxy( from.toSeq:_*) def hoge = map{ "hoge" + } } scala> val StringItrableProxy = new StringItrableProxy("aa", "bb", "cc", "abc") StringItrableProxy: StringItrableProxy = line56(aa, bb, cc, abc) scala> StringItrableProxy.filter{_.startsWith("a")} res8: StringItrableProxy = line56(aa, abc)