0
# Syntax Extensions
1
2
Scalaz provides implicit conversions and operators that extend standard types with functional programming methods, creating a convenient DSL for type class operations.
3
4
## Capabilities
5
6
### Functor Syntax
7
8
Extensions for types with Functor instances.
9
10
```scala { .api }
11
// Available via import scalaz.syntax.functor._ or import scalaz.Scalaz._
12
13
implicit class FunctorOps[F[_], A](self: F[A])(implicit F: Functor[F]) {
14
/** Map over the contained value */
15
def map[B](f: A => B): F[B] = F.map(self)(f)
16
17
/** Alias for map */
18
def <$>[B](f: A => B): F[B] = F.map(self)(f)
19
20
/** Discard the value, keeping structure */
21
def void: F[Unit] = F.void(self)
22
23
/** Pair original with result of function */
24
def fproduct[B](f: A => B): F[(A, B)] = F.fproduct(self)(f)
25
26
/** Replace all values with constant */
27
def as[B](b: => B): F[B] = F.map(self)(_ => b)
28
29
/** Strengthen with value on left */
30
def strengthL[B](b: B): F[(B, A)] = F.map(self)(a => (b, a))
31
32
/** Strengthen with value on right */
33
def strengthR[B](b: B): F[(A, B)] = F.map(self)(a => (a, b))
34
}
35
```
36
37
**Usage Examples:**
38
39
```scala
40
import scalaz._
41
import scalaz.syntax.functor._
42
43
List(1, 2, 3) <$> (_ * 2) // List(2, 4, 6)
44
List(1, 2, 3).void // List((), (), ())
45
List(1, 2, 3).fproduct(_ * 2) // List((1,2), (2,4), (3,6))
46
List(1, 2, 3).as("x") // List("x", "x", "x")
47
```
48
49
### Applicative Syntax
50
51
Extensions for types with Applicative instances.
52
53
```scala { .api }
54
// Available via import scalaz.syntax.applicative._ or import scalaz.Scalaz._
55
56
implicit class ApplicativeOps[F[_], A](self: F[A])(implicit F: Applicative[F]) {
57
/** Applicative builder for combining values */
58
def |@|[B](fb: F[B]): ApplicativeBuilder[F, A, B]
59
60
/** Apply a function in context */
61
def <*>[B](f: F[A => B]): F[B] = F.ap(self)(f)
62
63
/** Sequence and discard left value */
64
def *>[B](fb: F[B]): F[B] = F.apply2(self, fb)((_, b) => b)
65
66
/** Sequence and discard right value */
67
def <*[B](fb: F[B]): F[A] = F.apply2(self, fb)((a, _) => a)
68
}
69
70
implicit class ApplicativeBuilder[F[_], A, B](self: F[A] |@| F[B]) {
71
/** Apply binary function */
72
def apply[C](f: (A, B) => C): F[C]
73
74
/** Extend to ternary */
75
def |@|[C](fc: F[C]): ApplicativeBuilder3[F, A, B, C]
76
77
/** Create tuple */
78
def tupled: F[(A, B)]
79
}
80
81
// Point syntax for lifting values
82
implicit class ApplicativePointOps[A](self: A) {
83
def point[F[_]](implicit F: Applicative[F]): F[A] = F.point(self)
84
def pure[F[_]](implicit F: Applicative[F]): F[A] = F.point(self)
85
}
86
```
87
88
**Usage Examples:**
89
90
```scala
91
import scalaz._
92
import scalaz.syntax.applicative._
93
import scalaz.std.option._
94
95
// Applicative builder
96
val result = (some(1) |@| some(2) |@| some(3))(_ + _ + _) // Some(6)
97
98
// Point syntax
99
42.point[Option] // Some(42)
100
"hello".point[List] // List("hello")
101
102
// Sequencing
103
some(1) *> some(2) // Some(2)
104
some(1) <* some(2) // Some(1)
105
```
106
107
### Monad Syntax
108
109
Extensions for types with Monad instances.
110
111
```scala { .api }
112
// Available via import scalaz.syntax.monad._ or import scalaz.Scalaz._
113
114
implicit class MonadOps[F[_], A](self: F[A])(implicit F: Monad[F]) {
115
/** Monadic bind (flatMap) */
116
def >>=[B](f: A => F[B]): F[B] = F.bind(self)(f)
117
118
/** Alias for bind */
119
def flatMap[B](f: A => F[B]): F[B] = F.bind(self)(f)
120
121
/** Sequence and discard left value */
122
def >>[B](fb: => F[B]): F[B] = F.bind(self)(_ => fb)
123
124
/** Kleisli composition */
125
def >=>[B](f: A => F[B]): A => F[B] = a => F.bind(self)(f)
126
127
/** Join nested monads */
128
def join[B](implicit ev: A <:< F[B]): F[B] = F.join(self.map(ev))
129
130
/** Conditional execution */
131
def whenM(cond: F[Boolean])(implicit F: Monad[F]): F[Unit]
132
def unlessM(cond: F[Boolean])(implicit F: Monad[F]): F[Unit]
133
}
134
135
// Guard and filtering
136
implicit class MonadGuardOps[F[_]](implicit F: MonadPlus[F]) {
137
def guard(condition: Boolean): F[Unit] = F.guard(condition)
138
def prevent(condition: Boolean): F[Unit] = F.guard(!condition)
139
}
140
```
141
142
**Usage Examples:**
143
144
```scala
145
import scalaz._
146
import scalaz.syntax.monad._
147
import scalaz.std.list._
148
149
// Monadic bind
150
List(1, 2) >>= (x => List(x, x * 2)) // List(1, 2, 2, 4)
151
152
// Sequencing
153
List(1, 2) >> List(10, 20) // List(10, 20, 10, 20)
154
155
// For comprehensions work automatically
156
val result = for {
157
x <- List(1, 2)
158
y <- List(10, 20)
159
} yield x + y
160
```
161
162
### Foldable Syntax
163
164
Extensions for types with Foldable instances.
165
166
```scala { .api }
167
// Available via import scalaz.syntax.foldable._ or import scalaz.Scalaz._
168
169
implicit class FoldableOps[F[_], A](self: F[A])(implicit F: Foldable[F]) {
170
/** Fold with monoid */
171
def fold(implicit A: Monoid[A]): A = F.fold(self)
172
173
/** Map and fold */
174
def foldMap[B](f: A => B)(implicit B: Monoid[B]): B = F.foldMap(self)(f)
175
176
/** Right fold */
177
def foldRight[B](z: => B)(f: (A, => B) => B): B = F.foldRight(self, z)(f)
178
179
/** Left fold */
180
def foldLeft[B](z: B)(f: (B, A) => B): B = F.foldLeft(self, z)(f)
181
182
/** Convert to List */
183
def toList: List[A] = F.toList(self)
184
185
/** Length */
186
def length: Int = F.length(self)
187
188
/** Check if all satisfy predicate */
189
def all(p: A => Boolean): Boolean = F.all(self)(p)
190
191
/** Check if any satisfy predicate */
192
def any(p: A => Boolean): Boolean = F.any(self)(p)
193
194
/** Check if empty */
195
def empty: Boolean = F.empty(self)
196
197
/** Find element */
198
def find(p: A => Boolean): Option[A] = F.find(self)(p)
199
200
/** Count elements satisfying predicate */
201
def count(p: A => Boolean): Int = F.count(self)(p)
202
203
/** Sum elements */
204
def sum(implicit A: Monoid[A]): A = F.fold(self)
205
206
/** Product elements */
207
def product(implicit A: Monoid[A]): A = F.fold(self)
208
209
/** Maximum element */
210
def maximum(implicit A: Order[A]): Option[A] = F.maximum(self)
211
212
/** Minimum element */
213
def minimum(implicit A: Order[A]): Option[A] = F.minimum(self)
214
}
215
```
216
217
**Usage Examples:**
218
219
```scala
220
import scalaz._
221
import scalaz.syntax.foldable._
222
import scalaz.std.list._
223
224
List(1, 2, 3, 4).foldMap(_.toString) // "1234"
225
List(1, 2, 3, 4).all(_ > 0) // true
226
List(1, 2, 3, 4).any(_ > 3) // true
227
List(1, 2, 3, 4).count(_ % 2 == 0) // 2
228
List("a", "b", "c").find(_ == "b") // Some("b")
229
```
230
231
### Traverse Syntax
232
233
Extensions for types with Traverse instances.
234
235
```scala { .api }
236
// Available via import scalaz.syntax.traverse._ or import scalaz.Scalaz._
237
238
implicit class TraverseOps[F[_], A](self: F[A])(implicit F: Traverse[F]) {
239
/** Traverse with effects */
240
def traverse[G[_], B](f: A => G[B])(implicit G: Applicative[G]): G[F[B]] = F.traverse(self)(f)
241
242
/** Sequence effects */
243
def sequence[G[_], B](implicit ev: A <:< G[B], G: Applicative[G]): G[F[B]] = F.sequence(self.map(ev))
244
245
/** Map with accumulating state */
246
def mapAccumL[S, B](z: S)(f: (S, A) => (S, B)): (S, F[B]) = F.mapAccumL(self, z)(f)
247
248
/** Map with accumulating state (right) */
249
def mapAccumR[S, B](z: S)(f: (S, A) => (S, B)): (S, F[B]) = F.mapAccumR(self, z)(f)
250
251
/** Reverse the structure */
252
def reverse: F[A] = F.reverse(self)
253
}
254
```
255
256
**Usage Examples:**
257
258
```scala
259
import scalaz._
260
import scalaz.syntax.traverse._
261
import scalaz.std.list._
262
import scalaz.std.option._
263
264
// Traverse with Option
265
List(1, 2, 3).traverse(x => if (x > 0) Some(x * 2) else None) // Some(List(2, 4, 6))
266
267
// Sequence List of Options
268
List(Some(1), Some(2), Some(3)).sequence // Some(List(1, 2, 3))
269
List(Some(1), None, Some(3)).sequence // None
270
```
271
272
### Equal Syntax
273
274
Extensions for types with Equal instances.
275
276
```scala { .api }
277
// Available via import scalaz.syntax.equal._ or import scalaz.Scalaz._
278
279
implicit class EqualOps[A](self: A)(implicit A: Equal[A]) {
280
/** Type-safe equality */
281
def ===(other: A): Boolean = A.equal(self, other)
282
283
/** Type-safe inequality */
284
def /==(other: A): Boolean = !A.equal(self, other)
285
286
/** Assert equality (throws if false) */
287
def assert_===(other: A): A = {
288
if (!A.equal(self, other)) sys.error(s"Assertion failed: $self === $other")
289
self
290
}
291
}
292
```
293
294
**Usage Examples:**
295
296
```scala
297
import scalaz._
298
import scalaz.syntax.equal._
299
import scalaz.std.anyVal._
300
301
1 === 1 // true (uses Equal[Int])
302
1 /== 2 // true
303
"a" === "a" // true (uses Equal[String])
304
305
// Prevents comparison of different types
306
// 1 === "1" // Compilation error!
307
```
308
309
### Order Syntax
310
311
Extensions for types with Order instances.
312
313
```scala { .api }
314
// Available via import scalaz.syntax.order._ or import scalaz.Scalaz._
315
316
implicit class OrderOps[A](self: A)(implicit A: Order[A]) {
317
/** Compare and return Ordering */
318
def ?|?(other: A): Ordering = A.order(self, other)
319
320
/** Less than */
321
def <(other: A): Boolean = A.lessThan(self, other)
322
323
/** Less than or equal */
324
def <=(other: A): Boolean = A.lessThanOrEqual(self, other)
325
326
/** Greater than */
327
def >(other: A): Boolean = A.greaterThan(self, other)
328
329
/** Greater than or equal */
330
def >=(other: A): Boolean = A.greaterThanOrEqual(self, other)
331
332
/** Maximum */
333
def max(other: A): A = A.max(self, other)
334
335
/** Minimum */
336
def min(other: A): A = A.min(self, other)
337
338
/** Sort with another value */
339
def sort(other: A): (A, A) = if (A.lessThanOrEqual(self, other)) (self, other) else (other, self)
340
}
341
```
342
343
**Usage Examples:**
344
345
```scala
346
import scalaz._
347
import scalaz.syntax.order._
348
import scalaz.std.anyVal._
349
350
5 ?|? 3 // Ordering.GT
351
5 > 3 // true
352
5 max 10 // 10
353
5 min 10 // 5
354
5 sort 3 // (3, 5)
355
```
356
357
### Semigroup/Monoid Syntax
358
359
Extensions for types with Semigroup/Monoid instances.
360
361
```scala { .api }
362
// Available via import scalaz.syntax.semigroup._ or import scalaz.Scalaz._
363
364
implicit class SemigroupOps[A](self: A)(implicit A: Semigroup[A]) {
365
/** Semigroup append */
366
def |+|(other: => A): A = A.append(self, other)
367
368
/** Multiply (repeat operation) */
369
def multiply1(n: Int): A = A.multiply1(self, n)
370
}
371
372
// Available via import scalaz.syntax.monoid._ or import scalaz.Scalaz._
373
implicit class MonoidOps[A](self: A)(implicit A: Monoid[A]) {
374
/** Check if zero */
375
def isEmpty: Boolean = A.isMEmpty(self)
376
377
/** Multiply with zero handling */
378
def multiply(n: Int): A = A.multiply(self, n)
379
}
380
381
// Monoid zero
382
implicit class MonoidZeroOps[A](implicit A: Monoid[A]) {
383
def mzero: A = A.zero
384
}
385
```
386
387
**Usage Examples:**
388
389
```scala
390
import scalaz._
391
import scalaz.syntax.monoid._
392
import scalaz.std.string._
393
import scalaz.std.list._
394
395
"Hello" |+| " " |+| "World" // "Hello World"
396
List(1, 2) |+| List(3, 4) // List(1, 2, 3, 4)
397
List(1, 2).multiply(3) // List(1, 2, 1, 2, 1, 2)
398
mzero[String] // ""
399
```
400
401
### Show Syntax
402
403
Extensions for types with Show instances.
404
405
```scala { .api }
406
// Available via import scalaz.syntax.show._ or import scalaz.Scalaz._
407
408
implicit class ShowOps[A](self: A)(implicit A: Show[A]) {
409
/** Convert to string */
410
def shows: String = A.shows(self)
411
412
/** Convert to Cord */
413
def show: Cord = A.show(self)
414
415
/** Print to console */
416
def println: Unit = Predef.println(shows)
417
418
/** Print without newline */
419
def print: Unit = Predef.print(shows)
420
}
421
```
422
423
**Usage Examples:**
424
425
```scala
426
import scalaz._
427
import scalaz.syntax.show._
428
import scalaz.std.anyVal._
429
430
42.shows // "42"
431
42.println // Prints: 42
432
433
// Custom Show instances provide better output than toString
434
case class Person(name: String, age: Int)
435
implicit val personShow: Show[Person] = Show.shows(p => s"${p.name}(${p.age})")
436
Person("John", 30).shows // "John(30)"
437
```
438
439
### Validation Syntax
440
441
Extensions for working with Validation types.
442
443
```scala { .api }
444
// Available via import scalaz.syntax.validation._ or import scalaz.Scalaz._
445
446
implicit class ValidationOps[A](self: A) {
447
/** Create success validation */
448
def success[E]: Validation[E, A] = Success(self)
449
450
/** Create success validation with NonEmptyList error type */
451
def successNel[E]: ValidationNel[E, A] = Success(self)
452
}
453
454
implicit class ValidationErrorOps[E](self: E) {
455
/** Create failure validation */
456
def failure[A]: Validation[E, A] = Failure(self)
457
458
/** Create failure validation with NonEmptyList */
459
def failureNel[A]: ValidationNel[E, A] = Failure(NonEmptyList(self))
460
}
461
```
462
463
**Usage Examples:**
464
465
```scala
466
import scalaz._
467
import scalaz.syntax.validation._
468
import scalaz.syntax.applicative._
469
470
// Creating validations
471
val valid = "John".success[String]
472
val invalid = "Empty name".failure[String]
473
474
// Error accumulation
475
val result = (
476
"John".successNel[String] |@|
477
"Invalid age".failureNel[String] |@|
478
"john@example.com".successNel[String]
479
) { (name, age, email) => User(name, age, email) }
480
```
481
482
### Either/Disjunction Syntax
483
484
Extensions for Either and Disjunction (\/) types.
485
486
```scala { .api }
487
// Available via import scalaz.syntax.either._ or import scalaz.Scalaz._
488
489
implicit class EitherOps[A](self: A) {
490
/** Create left disjunction */
491
def left[B]: A \/ B = -\/(self)
492
493
/** Create right disjunction */
494
def right[B]: B \/ A = \/-(self)
495
}
496
497
implicit class DisjunctionOps[A, B](self: A \/ B) {
498
/** Alias for map */
499
def \/[C](f: B => C): A \/ C = self.map(f)
500
501
/** Get right or default */
502
def |(default: => B): B = self.getOrElse(default)
503
}
504
```
505
506
**Usage Examples:**
507
508
```scala
509
import scalaz._
510
import scalaz.syntax.either._
511
512
val success = 42.right[String] // String \/ Int = \/-(42)
513
val failure = "error".left[Int] // String \/ Int = -\/("error")
514
515
success | 0 // 42
516
failure | 0 // 0
517
```
518
519
### MonadPlus Syntax
520
521
Extensions for types with MonadPlus instances.
522
523
```scala { .api }
524
// Available via import scalaz.syntax.monadPlus._ or import scalaz.Scalaz._
525
526
implicit class MonadPlusOps[F[_], A](self: F[A])(implicit F: MonadPlus[F]) {
527
/** Filter with predicate */
528
def filter(p: A => Boolean): F[A] = F.filter(self)(p)
529
530
/** Alternative operator */
531
def <+>(other: => F[A]): F[A] = F.plus(self, other)
532
533
/** Return this if non-empty, otherwise alternative */
534
def orElse(alternative: => F[A]): F[A] = F.plus(self, alternative)
535
}
536
537
// Empty values
538
implicit class MonadPlusEmptyOps[F[_]](implicit F: MonadPlus[F]) {
539
def empty[A]: F[A] = F.empty[A]
540
}
541
```
542
543
**Usage Examples:**
544
545
```scala
546
import scalaz._
547
import scalaz.syntax.monadPlus._
548
import scalaz.std.list._
549
550
List(1, 2, 3, 4).filter(_ % 2 == 0) // List(2, 4)
551
List(1, 2) <+> List(3, 4) // List(1, 2, 3, 4)
552
List.empty[Int] orElse List(1, 2) // List(1, 2)
553
```
554
555
### Import Strategies
556
557
#### Complete Syntax Import
558
559
```scala { .api }
560
// Import all syntax extensions
561
import scalaz._
562
import Scalaz._
563
564
// Or import syntax package
565
import scalaz.syntax.all._
566
```
567
568
#### Selective Syntax Imports
569
570
```scala { .api }
571
// Import specific syntax
572
import scalaz.syntax.functor._ // Functor operations
573
import scalaz.syntax.applicative._ // Applicative operations
574
import scalaz.syntax.monad._ // Monad operations
575
import scalaz.syntax.foldable._ // Foldable operations
576
import scalaz.syntax.traverse._ // Traverse operations
577
import scalaz.syntax.equal._ // Equal operations
578
import scalaz.syntax.order._ // Order operations
579
import scalaz.syntax.semigroup._ // Semigroup operations
580
import scalaz.syntax.monoid._ // Monoid operations
581
import scalaz.syntax.show._ // Show operations
582
import scalaz.syntax.validation._ // Validation operations
583
import scalaz.syntax.either._ // Either/Disjunction operations
584
```
585
586
#### Combined Imports
587
588
```scala { .api }
589
// Common combination for everyday functional programming
590
import scalaz.{Applicative, Functor, Monad, Equal, Show, \/, ValidationNel}
591
import scalaz.syntax.applicative._
592
import scalaz.syntax.functor._
593
import scalaz.syntax.monad._
594
import scalaz.syntax.equal._
595
import scalaz.syntax.validation._
596
import scalaz.std.option._
597
import scalaz.std.list._
598
import scalaz.std.string._
599
```
600
601
**Usage Examples:**
602
603
```scala
604
import scalaz._
605
import Scalaz._
606
607
// All syntax available
608
val result = List(1, 2, 3)
609
.map(_ * 2) // Functor syntax
610
.filter(_ > 2) // MonadPlus syntax
611
.foldMap(_.toString) // Foldable syntax
612
613
val validation = (
614
"John".successNel[String] |@| // Validation syntax
615
25.successNel[String] |@| // Applicative syntax
616
"john@example.com".successNel[String]
617
) { User(_, _, _) }
618
619
val comparison = 1 === 1 && 5 > 3 // Equal and Order syntax
620
val combined = "Hello" |+| " World" // Monoid syntax
621
```