Token导航 LogoToken导航

Agent Skill · 研究检索

scala-type-system(scala 类型系统)

scala-type-system 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

scala-type-system 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在研究检索类的 73,675 个 Skill 里排第 10,526。

总安装 12,461周安装 394GitHub Stars 142下载 5,322核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:scala-type-system(scala 类型系统)
来源仓库:https://github.com/thebushidocollective/han
仓库路径:skills/scala-type-system
安装命令:
npx skills add https://github.com/thebushidocollective/han --skill 'Scala Type System'
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill 'Scala Type System'

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

scala-type-system 提供 Scala 类型系统深度解析与使用技巧。适合在 Codex、Claude、Cursor、Gemini CLI 中理解泛型、隐式与类型推导。通过 npx skills add 命令从 han 仓库安装使用。类型推导可能受编译器版本影响,需注意兼容性说明。

建议通过 REPL 或小型示例验证类型推断结果。

来源仓库内路径:skills/scala-type-system

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/thebushidocollective/han --skill 'Scala Type S…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

scala-type-system 怎么安装?

在终端执行 npx skills add https://github.com/thebushidocollective/han --skill 'Scala Type System'。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

scala-type-system 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

scala-type-system 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

scala-type-system 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

scala-type-system 用的人多吗?

公开数据是累计安装 12,461 次,近一周安装 394 次,下载 5,322 次,GitHub 142 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

scala-type-system 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
scala-type-system

scala 类型系统 · 本页

12,461142需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

Scala Type System

Introduction

Scala features one of the most sophisticated type systems among mainstream programming languages, combining object-oriented and functional programming concepts. This advanced type system enables precise modeling of domain concepts, compile-time verification of complex constraints, and highly reusable abstractions.

Key features include parametric polymorphism (generics), variance annotations, type bounds, implicit conversions and parameters, type classes, higher-kinded types, path-dependent types, and abstract type members. These features enable expressive APIs while maintaining type safety.

This skill covers generics and variance, upper and lower type bounds, view and context bounds, implicit conversions, type classes, higher-kinded types, path-dependent types, and practical type-level programming patterns.

Generics and Type Parameters

Type parameters enable writing reusable code that works with multiple types while maintaining type safety.

// Basic generic class
class Box[T](val content: T) {
  def get: T = content
  def map[U](f: T => U): Box[U] = new Box(f(content))
}

val intBox = new Box(42)
val stringBox = new Box("hello")

// Generic methods
def identity[T](x: T): T = x

def swap[A, B](pair: (A, B)): (B, A) = (pair._2, pair._1)

// Multiple type parameters
class Pair[A, B](val first: A, val second: B) {
  def swap: Pair[B, A] = new Pair(second, first)
}

// Generic collections
def first[T](list: List[T]): Option[T] = list.headOption

def last[T](list: List[T]): Option[T] = list.lastOption

// Type parameter constraints with type bounds
class NumberBox[T <: Number](val value: T) {
  def doubleValue: Double = value.doubleValue()
}

// Generic trait
trait Container[T] {
  def add(item: T): Container[T]
  def get: T
  def isEmpty: Boolean
}

class SimpleContainer[T](private var item: Option[T] = None)
  extends Container[T] {
  def add(newItem: T): Container[T] = {
    item = Some(newItem)
    this
  }

  def get: T = item.getOrElse(throw new NoSuchElementException)

  def isEmpty: Boolean = item.isEmpty
}

// Generic companion object
object Container {
  def empty[T]: Container[T] = new SimpleContainer[T]()

  def of[T](item: T): Container[T] = new SimpleContainer[T](Some(item))
}

// Type parameter inference
val box1 = new Box(42)           // Box[Int]
val box2 = new Box("hello")      // Box[String]
val list1 = List(1, 2, 3)        // List[Int]

// Explicit type parameters when needed
val box3 = new Box[Any](42)
val emptyList = List.empty[String]

// Generic functions with multiple constraints
def max[T](a: T, b: T)(implicit ord: Ordering[T]): T =
  if (ord.gt(a, b)) a else b

println(max(5, 10))              // 10
println(max("apple", "banana"))  // banana

// Type aliases for complex generic types
type StringMap[V] = Map[String, V]
type IntPair = (Int, Int)

val userAges: StringMap[Int] = Map("Alice" -> 30, "Bob" -> 25)
val point: IntPair = (10, 20)

Generics enable writing code once and reusing it with multiple types while maintaining compile-time type safety.

Variance Annotations

Variance controls how parameterized types relate to each other based on their type parameters' subtyping relationships.

// Covariance (+T): if A <: B, then Container[A] <: Container[B]
class CovariantBox[+T](val content: T) {
  def get: T = content
  // Can't have T in contravariant position (method parameters)
  // def set(item: T): Unit = ???  // Won't compile
}

class Animal
class Dog extends Animal
class Cat extends Animal

val dogBox: CovariantBox[Dog] = new CovariantBox(new Dog)
val animalBox: CovariantBox[Animal] = dogBox  // Valid due to covariance

// Contravariance (-T): if A <: B, then Container[B] <: Container[A]
trait Printer[-T] {
  def print(item: T): Unit
}

class AnimalPrinter extends Printer[Animal] {
  def print(animal: Animal): Unit = println("Animal")
}

val animalPrinter: Printer[Animal] = new AnimalPrinter
val dogPrinter: Printer[Dog] = animalPrinter  // Valid due to contravariance

// Invariance (T): no subtyping relationship
class InvariantBox[T](private var content: T) {
  def get: T = content
  def set(item: T): Unit = { content = item }
}

// Practical variance example: Function1
trait Function1[-T, +R] {
  def apply(v: T): R
}

val animalToString: Function1[Animal, String] = animal => "Animal"
val dogToAny: Function1[Dog, Any] = animalToString  // Valid

// Collections variance
val dogs: List[Dog] = List(new Dog, new Dog)
val animals: List[Animal] = dogs  // List is covariant

// Mutable collections are invariant
val dogArray: Array[Dog] = Array(new Dog)
// val animalArray: Array[Animal] = dogArray  // Won't compile

// Option is covariant
val someDog: Option[Dog] = Some(new Dog)
val someAnimal: Option[Animal] = someDog  // Valid

// Variance with multiple type parameters
class Function2[-T1, -T2, +R] {
  def apply(v1: T1, v2: T2): R = ???
}

// Variance bounds in definition
class Box[+T](val content: T) {
  // Use lower bound to allow contravariant position
  def set[U >: T](item: U): Box[U] = new Box(item)
}

// Either is covariant in both parameters
sealed trait Either[+A, +B]
case class Left[A](value: A) extends Either[A, Nothing]
case class Right[B](value: B) extends Either[Nothing, B]

val rightInt: Either[String, Int] = Right(42)
val rightAny: Either[String, Any] = rightInt  // Valid

Variance annotations make parameterized types more flexible while maintaining type safety, especially for immutable containers.

Type Bounds

Type bounds constrain type parameters to specific type hierarchies, enabling type-safe operations on generic types.

// Upper type bound (T <: Upper)
def findMax[T <: Ordered[T]](list: List[T]): Option[T] = {
  if (list.isEmpty) None
  else Some(list.reduce((a, b) => if (a > b) a else b))
}

// Lower type bound (T >: Lower)
class Animal
class Dog extends Animal

class Container[+T] {
  def add[U >: T](item: U): Container[U] = ???
}

// Using both bounds together
def cloneAndReset[T >: Null <: Cloneable](obj: T): T = {
  val cloned = obj.clone().asInstanceOf[T]
  cloned
}

// Complex type bounds
trait Comparable[T] {
  def compareTo(that: T): Int
}

def sort[T <: Comparable[T]](list: List[T]): List[T] =
  list.sortWith(_.compareTo(_) < 0)

// Multiple bounds with 'with'
trait Loggable {
  def log(): Unit
}

trait Serializable {
  def serialize(): String
}

def process[T <: Loggable with Serializable](item: T): String = {
  item.log()
  item.serialize()
}

// Recursive type bounds (F-bounded polymorphism)
trait Comparable2[T <: Comparable2[T]] { self: T =>
  def compare(that: T): Int
}

class Person(val name: String, val age: Int) extends Comparable2[Person] {
  def compare(that: Person): Int = this.age - that.age
}

// View bounds (deprecated but useful to understand)
// def sum[T <% Ordered[T]](list: List[T]): T = ???

// Context bounds (modern approach)
def sum[T: Numeric](list: List[T]): T = {
  val numeric = implicitly[Numeric[T]]
  list.foldLeft(numeric.zero)(numeric.plus)
}

println(sum(List(1, 2, 3)))           // 6
println(sum(List(1.5, 2.5, 3.0)))     // 7.0

// Multiple context bounds
def print[T: Ordering: Numeric](list: List[T]): Unit = {
  val ord = implicitly[Ordering[T]]
  val num = implicitly[Numeric[T]]
  println(s"Max: ${list.max(ord)}, Sum: ${sum(list)}")
}

// Abstract type members with bounds
trait Container2 {
  type Content <: AnyRef
  def get: Content
}

class StringContainer extends Container2 {
  type Content = String
  def get: String = "hello"
}

// Type bounds with variance
class Box[+T] {
  def put[U >: T](item: U): Box[U] = new Box[U]
}

// Existential types (less common)
def processAnyBox(box: Box[_]): Unit = {
  println("Processing box")
}

// Type bounds for type classes
trait Show[T] {
  def show(value: T): String
}

def display[T: Show](value: T): String = {
  val shower = implicitly[Show[T]]
  shower.show(value)
}

implicit val intShow: Show[Int] = (value: Int) => value.toString
implicit val stringShow: Show[String] = (value: String) => s"\"$value\""

println(display(42))        // "42"
println(display("hello"))   // "\"hello\""

Type bounds enable precise constraints on generic types while maintaining flexibility and type safety.

Implicit Conversions and Parameters

Implicits enable automatic type conversions, provide evidence of type relationships, and inject dependencies.

// Implicit conversions
implicit def intToString(x: Int): String = x.toString

val s: String = 42  // Automatically converts via implicit

// Extension methods via implicit classes
implicit class RichInt(val value: Int) extends AnyVal {
  def times(f: => Unit): Unit = {
    (1 to value).foreach(_ => f)
  }

  def squared: Int = value * value
}

5.times(println("Hello"))
println(10.squared)  // 100

// Implicit parameters
def greet(name: String)(implicit greeting: String): String =
  s"$greeting, $name!"

implicit val defaultGreeting: String = "Hello"
println(greet("Alice"))  // "Hello, Alice!"

// Multiple implicit parameters
def format(value: Double)(implicit precision: Int, prefix: String): String =
  s"$prefix${BigDecimal(value).setScale(precision, BigDecimal.RoundingMode.HALF_UP)}"

implicit val precision: Int = 2
implicit val prefix: String = "$"

println(format(123.456))  // "$123.46"

// Implicit parameters for type classes
trait Monoid[T] {
  def empty: T
  def combine(a: T, b: T): T
}

implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
  def empty: Int = 0
  def combine(a: Int, b: Int): Int = a + b
}

implicit val stringMonoid: Monoid[String] = new Monoid[String] {
  def empty: String = ""
  def combine(a: String, b: String): String = a + b
}

def combineAll[T](list: List[T])(implicit monoid: Monoid[T]): T =
  list.foldLeft(monoid.empty)(monoid.combine)

println(combineAll(List(1, 2, 3)))           // 6
println(combineAll(List("a", "b", "c")))     // "abc"

// Implicit evidence
def listToString[T](list: List[T])(implicit ev: T =:= String): String =
  list.mkString(", ")

println(listToString(List("a", "b", "c")))
// println(listToString(List(1, 2, 3)))  // Won't compile

// Type constraints
def onlyNumbers[T](value: T)(implicit ev: T <:< Number): Double =
  value.doubleValue()

// Implicit resolution
object Implicits {
  implicit val defaultTimeout: Int = 5000
}

def fetchData(url: String)(implicit timeout: Int): String = {
  s"Fetching $url with timeout $timeout"
}

import Implicits._
println(fetchData("http://example.com"))

// Implicit classes for DSLs
implicit class StringOps(val s: String) extends AnyVal {
  def toIntOpt: Option[Int] = try Some(s.toInt)
    catch { case _: Exception => None }
}

println("123".toIntOpt)   // Some(123)
println("abc".toIntOpt)   // None

// Implicit conversions for numeric types
implicit def intToRational(x: Int): Rational = Rational(x, 1)

case class Rational(numerator: Int, denominator: Int) {
  def +(that: Rational): Rational =
    Rational(
      numerator * that.denominator + that.numerator * denominator,
      denominator * that.denominator
    )
}

val r = Rational(1, 2) + 3  // 3 converted to Rational(3, 1)

Implicits enable powerful patterns like extension methods, type classes, and dependency injection while maintaining type safety.

Type Classes

Type classes provide ad-hoc polymorphism, enabling extension of types without modification and separation of concerns.

// Define type class
trait Show[T] {
  def show(value: T): String
}

// Implement instances
object Show {
  implicit val intShow: Show[Int] = new Show[Int] {
    def show(value: Int): String = value.toString
  }

  implicit val stringShow: Show[String] = new Show[String] {
    def show(value: String): String = s"\"$value\""
  }

  implicit val boolShow: Show[Boolean] = new Show[Boolean] {
    def show(value: Boolean): String = value.toString
  }

  // Generic instance for List
  implicit def listShow[T: Show]: Show[List[T]] = new Show[List[T]] {
    def show(list: List[T]): String = {
      val shower = implicitly[Show[T]]
      list.map(shower.show).mkString("[", ", ", "]")
    }
  }

  // Syntax for convenient usage
  implicit class ShowOps[T](val value: T) extends AnyVal {
    def show(implicit shower: Show[T]): String = shower.show(value)
  }
}

import Show._

println(42.show)                    // "42"
println("hello".show)               // "\"hello\""
println(List(1, 2, 3).show)         // "[1, 2, 3]"

// Ordering type class
trait Ord[T] {
  def compare(a: T, b: T): Int
  def lt(a: T, b: T): Boolean = compare(a, b) < 0
  def gt(a: T, b: T): Boolean = compare(a, b) > 0
}

object Ord {
  implicit val intOrd: Ord[Int] = new Ord[Int] {
    def compare(a: Int, b: Int): Int = a - b
  }

  implicit val stringOrd: Ord[String] = new Ord[String] {
    def compare(a: String, b: String): Int = a.compareTo(b)
  }
}

def sort[T: Ord](list: List[T]): List[T] = {
  val ord = implicitly[Ord[T]]
  list.sortWith((a, b) => ord.lt(a, b))
}

// JSON serialization type class
trait JsonWriter[T] {
  def write(value: T): String
}

object JsonWriter {
  implicit val intWriter: JsonWriter[Int] =
    (value: Int) => value.toString

  implicit val stringWriter: JsonWriter[String] =
    (value: String) => s""""$value""""

  implicit val boolWriter: JsonWriter[Boolean] =
    (value: Boolean) => value.toString

  implicit def listWriter[T: JsonWriter]: JsonWriter[List[T]] =
    (list: List[T]) => {
      val writer = implicitly[JsonWriter[T]]
      list.map(writer.write).mkString("[", ",", "]")
    }

  implicit def mapWriter[T: JsonWriter]: JsonWriter[Map[String, T]] =
    (map: Map[String, T]) => {
      val writer = implicitly[JsonWriter[T]]
      map.map { case (k, v) => s""""$k":${writer.write(v)}""" }
        .mkString("{", ",", "}")
    }
}

def toJson[T: JsonWriter](value: T): String = {
  implicitly[JsonWriter[T]].write(value)
}

// Functor type class
trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}

object Functor {
  implicit val listFunctor: Functor[List] = new Functor[List] {
    def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
  }

  implicit val optionFunctor: Functor[Option] = new Functor[Option] {
    def map[A, B](fa: Option[A])(f: A => B): Option[B] = fa.map(f)
  }
}

def increment[F[_]: Functor](container: F[Int]): F[Int] = {
  implicitly[Functor[F]].map(container)(_ + 1)
}

println(increment(List(1, 2, 3)))      // List(2, 3, 4)
println(increment(Some(5)))            // Some(6)

// Semigroup and Monoid type classes
trait Semigroup[T] {
  def combine(a: T, b: T): T
}

trait Monoid[T] extends Semigroup[T] {
  def empty: T
}

object Monoid {
  implicit val intMonoid: Monoid[Int] = new Monoid[Int] {
    def empty: Int = 0
    def combine(a: Int, b: Int): Int = a + b
  }

  implicit val stringMonoid: Monoid[String] = new Monoid[String] {
    def empty: String = ""
    def combine(a: String, b: String): String = a + b
  }

  implicit def listMonoid[T]: Monoid[List[T]] = new Monoid[List[T]] {
    def empty: List[T] = List.empty
    def combine(a: List[T], b: List[T]): List[T] = a ++ b
  }
}

def fold[T: Monoid](list: List[T]): T = {
  val monoid = implicitly[Monoid[T]]
  list.foldLeft(monoid.empty)(monoid.combine)
}

println(fold(List(1, 2, 3)))           // 6
println(fold(List("a", "b", "c")))     // "abc"

Type classes enable adding functionality to existing types without modification and provide compile-time polymorphism.

Higher-Kinded Types

Higher-kinded types abstract over type constructors, enabling generic programming over container types.

// Higher-kinded type parameter (F[_])
trait Container[F[_]] {
  def wrap[A](value: A): F[A]
}

object Container {
  implicit val listContainer: Container[List] = new Container[List] {
    def wrap[A](value: A): List[A] = List(value)
  }

  implicit val optionContainer: Container[Option] = new Container[Option] {
    def wrap[A](value: A): Option[A] = Some(value)
  }
}

def wrapValue[F[_]: Container, A](value: A): F[A] =
  implicitly[Container[F]].wrap(value)

println(wrapValue[List, Int](42))      // List(42)
println(wrapValue[Option, String]("hi"))  // Some(hi)

// Functor with higher-kinded types
trait Functor[F[_]] {
  def map[A, B](fa: F[A])(f: A => B): F[B]
}

object Functor {
  implicit val listFunctor: Functor[List] = new Functor[List] {
    def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
  }
}

def transformContainer[F[_]: Functor, A, B](container: F[A])(f: A => B): F[B] =
  implicitly[Functor[F]].map(container)(f)

// Monad with higher-kinded types
trait Monad[F[_]] {
  def pure[A](value: A): F[A]
  def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]

  def map[A, B](fa: F[A])(f: A => B): F[B] =
    flatMap(fa)(a => pure(f(a)))
}

object Monad {
  implicit val optionMonad: Monad[Option] = new Monad[Option] {
    def pure[A](value: A): Option[A] = Some(value)
    def flatMap[A, B](fa: Option[A])(f: A => Option[B]): Option[B] =
      fa.flatMap(f)
  }

  implicit val listMonad: Monad[List] = new Monad[List] {
    def pure[A](value: A): List[A] = List(value)
    def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] =
      fa.flatMap(f)
  }
}

def sequenceOperations[F[_]: Monad, A, B, C](
  fa: F[A],
  f: A => F[B],
  g: B => F[C]
): F[C] = {
  val monad = implicitly[Monad[F]]
  monad.flatMap(fa)(a => monad.flatMap(f(a))(g))
}

// Traverse type class
trait Traverse[F[_]] {
  def traverse[G[_]: Monad, A, B](fa: F[A])(f: A => G[B]): G[F[B]]
}

// Applicative with higher-kinded types
trait Applicative[F[_]] {
  def pure[A](value: A): F[A]
  def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]

  def map2[A, B, C](fa: F[A], fb: F[B])(f: (A, B) => C): F[C] =
    ap(map(fa)(a => (b: B) => f(a, b)))(fb)

  def map[A, B](fa: F[A])(f: A => B): F[B] =
    ap(pure(f))(fa)
}

// Free monad pattern
sealed trait Free[F[_], A]
case class Pure[F[_], A](value: A) extends Free[F, A]
case class FlatMap[F[_], A, B](fa: Free[F, A], f: A => Free[F, B])
  extends Free[F, B]
case class Suspend[F[_], A](fa: F[A]) extends Free[F, A]

Higher-kinded types enable abstracting over effect types and writing highly generic, reusable code.

Path-Dependent Types and Abstract Type Members

Path-dependent types tie type definitions to specific instances, enabling precise type relationships.

// Path-dependent types
class Outer {
  class Inner {
    def greet(): String = "Hello from Inner"
  }

  val inner = new Inner
}

val outer1 = new Outer
val outer2 = new Outer

val inner1: outer1.Inner = new outer1.Inner
// val inner2: outer1.Inner = new outer2.Inner  // Won't compile - different paths

// Abstract type members
trait Container3 {
  type Content
  def get: Content
  def set(value: Content): Unit
}

class StringContainer extends Container3 {
  type Content = String
  private var value: String = ""

  def get: String = value
  def set(newValue: String): Unit = { value = newValue }
}

class IntContainer extends Container3 {
  type Content = Int
  private var value: Int = 0

  def get: Int = value
  def set(newValue: Int): Unit = { value = newValue }
}

// Using abstract type members
def transfer(from: Container3,
             to: Container3 { type Content = from.Content }): Unit = {
  to.set(from.get)
}

// Type refinement
trait Animal2 {
  type SuitableFood
  def eat(food: SuitableFood): Unit
}

class Grass
class Meat

class Cow extends Animal2 {
  type SuitableFood = Grass
  def eat(food: Grass): Unit = println("Cow eats grass")
}

class Lion extends Animal2 {
  type SuitableFood = Meat
  def eat(food: Meat): Unit = println("Lion eats meat")
}

// Self-type annotations
trait User2 {
  def username: String
}

trait Tweeter {
  self: User2 =>  // Self-type: Tweeter requires User2
  def tweet(message: String): String = s"$username: $message"
}

class Account(val username: String) extends User2 with Tweeter

val account = new Account("alice")
println(account.tweet("Hello!"))

// Family polymorphism
trait Graph {
  type Node
  type Edge

  def addNode(node: Node): Unit
  def addEdge(edge: Edge): Unit
}

class DirectedGraph extends Graph {
  type Node = String
  type Edge = (String, String)

  def addNode(node: String): Unit = println(s"Adding node: $node")
  def addEdge(edge: (String, String)): Unit =
    println(s"Adding edge: ${edge._1} -> ${edge._2}")
}

Path-dependent types and abstract type members enable sophisticated type relationships and family polymorphism patterns.

Best Practices

  1. Use variance annotations appropriately on immutable containers for flexibility while avoiding on mutable ones
  2. Prefer abstract type members over type parameters when modeling families of related types
  3. Apply context bounds for type class constraints to keep signatures clean and readable
  4. Use implicit classes for extension methods rather than implicit conversions for safety
  5. Make implicit parameters explicit in public APIs for clarity and documentation
  6. Leverage type bounds to constrain generic types and enable type-safe operations
  7. Define type classes in companion objects to enable automatic implicit resolution
  8. Use sealed traits with case classes for ADTs to ensure exhaustive pattern matching
  9. Apply higher-kinded types when abstracting over effect types like Future, Option, or Either
  10. Keep implicit scope small to avoid resolution conflicts and maintain predictability

Common Pitfalls

  1. Overusing implicits makes code hard to understand and debug due to hidden conversions
  2. Forgetting variance annotations on immutable containers loses flexibility in APIs
  3. Using upper bounds exclusively when lower bounds needed causes compilation errors
  4. Creating ambiguous implicits in scope causes resolution failures and confusing errors
  5. Not marking implicit conversions with proper naming conventions makes code unclear
  6. Applying covariance to mutable containers breaks type safety and enables runtime errors
  7. Overcomplicating with higher-kinded types prematurely adds complexity without clear benefits
  8. Not using type aliases for complex generic types reduces readability significantly
  9. Mixing path-dependent types carelessly causes type incompatibility issues
  10. Forgetting type class coherence by defining multiple instances causes unpredictable behavior

When to Use This Skill

Apply advanced type system features when building reusable libraries and frameworks requiring flexibility.

Use variance annotations when designing immutable container types or APIs that should accept subtypes.

Leverage type classes when extending third-party types without modification or providing ad-hoc polymorphism.

Apply higher-kinded types when abstracting over effect types in functional programming patterns.

Use path-dependent types when modeling relationships between types tied to specific instances.

Employ abstract type members when designing APIs with families of related types.

Resources

平台分布

Codex

38.59%
按下载量换算2,054

Claude

32.36%
按下载量换算1,722

Cursor

16.99%
按下载量换算904

Gemini CLI

8.48%
按下载量换算451

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills