or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

tessl/maven-com-chuusai--shapeless-2-11

An exploration of generic (aka polytypic) programming in Scala derived from implementing scrap your boilerplate and higher rank polymorphism patterns

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
mavenpkg:maven/com.chuusai/shapeless_2.11@1.2.x

To install, run

npx @tessl/cli install tessl/maven-com-chuusai--shapeless-2-11@1.2.0

0

# Shapeless

1

2

Shapeless is a type class and dependent type based generic programming library for Scala. It provides powerful abstractions for working with heterogeneous data structures and enables type-safe generic programming through compile-time type manipulation and automatic type class derivation.

3

4

## Package Information

5

6

- **Package Name**: shapeless

7

- **Package Type**: Scala library

8

- **Version**: 1.2.4

9

- **Language**: Scala

10

- **Installation**: Add to your `build.sbt`:

11

12

```scala

13

libraryDependencies += "com.chuusai" %% "shapeless" % "1.2.4"

14

```

15

16

## Core Imports

17

18

```scala { .api }

19

import shapeless._

20

```

21

22

For specific functionality, use targeted imports:

23

24

```scala { .api }

25

import shapeless.HList._

26

import shapeless.Poly._

27

import shapeless.Nat._

28

import shapeless.record._

29

import shapeless.syntax.sized._

30

```

31

32

## Basic Usage

33

34

```scala { .api }

35

import shapeless._

36

37

// Create heterogeneous lists

38

val hlist = 23 :: "foo" :: true :: HNil

39

val head: Int = hlist.head

40

val tail = hlist.tail

41

42

// Type-safe record operations

43

val book = ("author" ->> "Benjamin Pierce") :: ("title" ->> "TAPL") :: ("id" ->> 991) :: HNil

44

val author: String = book("author")

45

val updated = book.updated("price", 89.95)

46

47

// Polymorphic functions

48

object size extends Poly1 {

49

implicit def caseInt = at[Int](identity)

50

implicit def caseString = at[String](_.length)

51

implicit def caseList[T] = at[List[T]](_.length)

52

}

53

54

val sizes = (42 :: "hello" :: List(1, 2, 3) :: HNil).map(size)

55

// sizes: Int :: Int :: Int :: HNil = 42 :: 5 :: 3 :: HNil

56

57

// Heterogeneous maps with type-level relations

58

class BiMapIS[K, V]

59

implicit val intToString = new BiMapIS[Int, String]

60

implicit val stringToInt = new BiMapIS[String, Int]

61

62

val hmap = HMap[BiMapIS](23 -> "twenty-three", "age" -> 30)

63

val str: Option[String] = hmap.get(23) // Some("twenty-three")

64

val int: Option[Int] = hmap.get("age") // Some(30)

65

66

// Function lifting into Option

67

val add: (Int, Int) => Int = _ + _

68

val safeAdd = Lift.liftO(add) // (Option[Int], Option[Int]) => Option[Int]

69

val result = safeAdd(Some(5), Some(3)) // Some(8)

70

val failed = safeAdd(Some(5), None) // None

71

72

// Generic transformations with SYB

73

case class Person(name: String, age: Int)

74

val person = Person("Alice", 30)

75

76

object incrementAge extends Poly1 {

77

implicit def caseInt = at[Int](_ + 1)

78

implicit def default[T] = at[T](identity)

79

}

80

81

val olderPerson = person.everywhere(incrementAge)

82

// Person("Alice", 31) - age incremented, name unchanged

83

```

84

85

## Architecture

86

87

Shapeless is built around several core concepts that work together to enable generic programming:

88

89

- **HList (Heterogeneous Lists)**: Statically typed lists that can contain elements of different types, providing the foundation for type-safe generic operations

90

- **Type-level Programming**: Natural numbers (`Nat`) and type-level computations enable compile-time verification and manipulation

91

- **Polymorphic Functions**: `Poly` functions allow type-specific behavior while maintaining a single interface

92

- **Isomorphisms**: Bidirectional type transformations (`Iso`) enable safe conversions between equivalent representations

93

- **Automatic Derivation**: Type class instances can be automatically derived for case classes and other algebraic data types

94

- **Compile-time Safety**: All operations are verified at compile time, eliminating runtime type errors

95

96

## Capabilities

97

98

### Heterogeneous Lists (HList)

99

100

Core data structure for holding statically typed sequences of different types. Provides rich operations for manipulation, transformation, and type-safe access.

101

102

```scala { .api }

103

sealed trait HList

104

final case class ::[+H, +T <: HList](head: H, tail: T) extends HList

105

case object HNil extends HNil

106

107

// Enhanced operations through HListOps

108

class HListOps[L <: HList](l: L) {

109

def head(implicit c: IsHCons[L]): c.H

110

def tail(implicit c: IsHCons[L]): c.T

111

def ::[H](h: H): H :: L

112

def ++[S <: HList](suffix: S)(implicit prepend: Prepend[L, S]): prepend.Out

113

def reverse(implicit reverse: Reverse[L]): reverse.Out

114

def map[HF](f: HF)(implicit mapper: Mapper[HF, L]): mapper.Out

115

}

116

```

117

118

[HList Operations](./hlist.md)

119

120

### Polymorphic Functions

121

122

Type-safe polymorphic functions that can have different behavior for different types while maintaining a unified interface.

123

124

```scala { .api }

125

trait Poly extends Product with Serializable

126

127

trait Poly1 extends Poly {

128

def at[T] = new Case1Builder[T]

129

def apply[T](t: T)(implicit c: Case1[T]): c.R

130

}

131

132

// Natural transformations

133

trait ~>[F[_], G[_]] extends Poly1 {

134

def apply[T](f: F[T]): G[T]

135

}

136

```

137

138

[Polymorphic Functions](./poly.md)

139

140

### Type-level Natural Numbers

141

142

Compile-time natural number arithmetic for expressing constraints and computations at the type level.

143

144

```scala { .api }

145

trait Nat

146

case class Succ[P <: Nat]() extends Nat

147

class _0 extends Nat

148

149

// Arithmetic operations

150

trait Sum[A <: Nat, B <: Nat] { type Out <: Nat }

151

trait Diff[A <: Nat, B <: Nat] { type Out <: Nat }

152

trait Prod[A <: Nat, B <: Nat] { type Out <: Nat }

153

154

// Comparison operations

155

trait LT[A <: Nat, B <: Nat]

156

type <[A <: Nat, B <: Nat] = LT[A, B]

157

```

158

159

[Type-level Natural Numbers](./nat.md)

160

161

### Type-safe Records

162

163

HList-based records with compile-time field access and type-safe manipulation operations.

164

165

```scala { .api }

166

trait Field[T] extends FieldAux { type valueType = T }

167

type FieldEntry[F <: FieldAux] = (F, F#valueType)

168

169

class RecordOps[L <: HList](l: L) {

170

def get[F <: FieldAux](f: F)(implicit selector: Selector[L, FieldEntry[F]]): F#valueType

171

def updated[V, F <: Field[V]](f: F, v: V)(implicit updater: Updater[L, F, V]): updater.Out

172

def +[V, F <: Field[V]](fv: (F, V))(implicit updater: Updater[L, F, V]): updater.Out

173

def -[F <: FieldAux](f: F)(implicit remove: Remove[FieldEntry[F], L]): remove.Out

174

}

175

```

176

177

[Type-safe Records](./records.md)

178

179

### Type-safe Conversions

180

181

Bidirectional conversions between tuples, functions, and HLists with compile-time safety guarantees.

182

183

```scala { .api }

184

// Tuple to HList conversion

185

trait HLister[T <: Product] { type Out <: HList; def apply(t: T): Out }

186

187

// Function conversions

188

trait FnHLister[F] { type Out; def apply(f: F): Out }

189

trait FnUnHLister[F] { type Out; def apply(f: F): Out }

190

191

// Traversable conversions

192

trait FromTraversable[Out <: HList] {

193

def apply(l: GenTraversable[_]): Option[Out]

194

}

195

```

196

197

[Type-safe Conversions](./conversions.md)

198

199

### Generic Programming Utilities

200

201

Advanced utilities for functional references, navigation, and transformations including lenses, zippers, and isomorphisms.

202

203

```scala { .api }

204

// Lenses for functional references

205

trait Lens[C, F] {

206

def get(c: C): F

207

def set(c: C)(f: F): C

208

def modify(c: C)(f: F => F): C

209

}

210

211

// Zippers for navigation and updates

212

case class Zipper[C, L <: HList, R <: HList, P](prefix: L, suffix: R, parent: P)

213

214

// Isomorphisms for bidirectional conversions

215

trait Iso[T, U] {

216

def to(t: T): U

217

def from(u: U): T

218

def reverse: Iso[U, T]

219

}

220

```

221

222

[Generic Programming Utilities](./generic.md)

223

224

### Sized Collections

225

226

Collections with statically known size, providing compile-time length verification and safe operations.

227

228

```scala { .api }

229

abstract class Sized[+Repr, L <: Nat](r: Repr) {

230

type A

231

def unsized = r

232

}

233

234

class SizedOps[A, Repr, L <: Nat] {

235

def head(implicit ev: _0 < L): A

236

def tail(implicit pred: Pred[L]): Sized[Repr, pred.Out]

237

def take[M <: Nat](implicit diff: Diff[L, M]): Sized[Repr, M]

238

def drop[M <: Nat](implicit diff: Diff[L, M]): Sized[Repr, diff.Out]

239

}

240

```

241

242

[Sized Collections](./sized.md)

243

244

### Type Operators and Advanced Types

245

246

Type-level logic operations, inequalities, tagged types, and advanced type programming constructs.

247

248

```scala { .api }

249

type Id[+T] = T

250

type ¬[T] = T => Nothing

251

type ∧[T, U] = T with U

252

type ∨[T, U] = ¬[¬[T] ∧ ¬[U]]

253

254

// Type inequalities

255

trait =:!=[A, B] // Type inequality witness

256

trait <:!<[A, B] // Subtype inequality witness

257

258

// Tagged types

259

type @@[T, U] = T with Tagged[U]

260

```

261

262

[Type Operators](./typeoperators.md)

263

264

### Runtime Type Safety

265

266

Runtime type-safe casting with compile-time guarantees through the `Typeable` type class.

267

268

```scala { .api }

269

trait Typeable[U] {

270

def cast(t: Any): Option[U]

271

}

272

273

class Cast(t: Any) {

274

def cast[U](implicit castU: Typeable[U]): Option[U]

275

}

276

```

277

278

[Runtime Type Safety](./typeable.md)

279

280

### Heterogeneous Maps (HMap)

281

282

Type-safe maps where keys and values can have different types, with relationships enforced at compile time through type-level relations.

283

284

```scala { .api }

285

class HMap[R[_, _]](underlying: Map[Any, Any] = Map.empty) extends Poly {

286

def get[K, V](k: K)(implicit ev: R[K, V]): Option[V]

287

def +[K, V](kv: (K, V))(implicit ev: R[K, V]): HMap[R]

288

def -[K](k: K): HMap[R]

289

}

290

```

291

292

[Heterogeneous Maps](./hmap.md)

293

294

### Function Lifting

295

296

Utilities for lifting ordinary functions of arbitrary arity into various contexts such as Option, enabling safe handling of potentially absent values.

297

298

```scala { .api }

299

object Lift {

300

def liftO[InF, InL <: HList, R, OInL <: HList, OutF](f: InF): OutF

301

}

302

```

303

304

[Function Lifting](./lift.md)

305

306

### Scrap Your Boilerplate (SYB)

307

308

Generic programming combinators for queries and transformations over arbitrarily nested data structures without explicit recursion.

309

310

```scala { .api }

311

trait Data[F, T, R] {

312

def gmapQ(f: F, t: T): R

313

}

314

315

trait DataT[F, T] {

316

def gmapT(f: F, t: T): T

317

}

318

319

def everything[F <: Poly](f: F): ...

320

def everywhere[F <: Poly](f: F): ...

321

```

322

323

[Scrap Your Boilerplate](./sybclass.md)