Skip to content

Latest commit

 

History

History
115 lines (102 loc) · 2.78 KB

README.md

File metadata and controls

115 lines (102 loc) · 2.78 KB

Scalanum

Scalanum - is the Enum and Bounded type classes implemented in Scala. The implementation is inspired by the corresponding type class in Haskell. These particular type classes are missing in Cats and I don't really want to bring Scalaz to my projects because of this small inconvenience. That's why I came up with my own minimalistic version of Enum and Bounded with zero external dependencies. Below are some useful examples.

First we need to prepare the environment:

sbt clean package
scala -cp ./scalanum/target/scala-2.11/scalanum_2.11-0.1.jar

For our example we use the following sum type:

sealed trait Animal
case object Cat extends Animal
case object Dog extends Animal
case object Rabbit extends Animal
case object Cow extends Animal

The Enum instance for the sum type above might look like following:

import scalanum._

implicit val animalEnum = new Enum[Animal] {
  val animals = Array(Cat, Dog, Rabbit, Cow)
  override def fromEnum(a: Animal): Int = animals.indexOf(a)
  override def toEnum(i: Int): Animal = animals(i)
}

Or the same but shorter:

import scalanum._

implicit val animalEnum = new EnumIndexed[Animal] {
  override val list: IndexedSeq[Animal] = Array(Cat, Dog, Rabbit, Cow)
}

Now let's play with it:

scala> Enum[Animal].succ(Cat)
res0: Animal = Dog

scala> Enum[Animal].pred(Cow)
res1: Animal = Rabbit

Scalanum is able to generate collections of enumerated values:

scala> Enum[Animal].fromTo(Cat, Rabbit).foreach(println)
Cat
Dog
Rabbit

Note: if you use a EnumIndexed approach you get upper and lower bounds for your enumeration automatically:

scala> Enum[Animal].from(Dog).foreach(println)
Dog
Rabbit
Cow

The Enum instance for integers and chars are already included into the library. Due to the lazy nature of generated collections we can produce "infinite" sequences:

scala> Enum[Char].from('a').take(5).foreach(println)
a
b
c
d
e

scala> Enum[Int].from(1).filter(_ % 2 == 0).takeWhile(_ < 20).foreach(println)
2
4
6
8
10
12
14
16
18

We can also specify a custom progression pattern:

scala> Enum[Char].fromThenTo('a', 'c', 'h').foreach(println)
a
c
e
g

scala> Enum[Int].fromThenTo(1, 5, 20).foreach(println)
1
5
9
13
17

At last a small real world example:

import scalanum._

sealed trait TrafficLight
case object Green extends TrafficLight
case object Yellow extends TrafficLight
case object Red extends TrafficLight

implicit val trafficLightEnum = new EnumIndexed[TrafficLight] {
  override val list: IndexedSeq[TrafficLight] = Array(Green, Yellow, Red)
}

scala> Enum[TrafficLight].succ(Green)
res0: TrafficLight = Yellow

scala> Enum[TrafficLight].succ(Enum[TrafficLight].succ(Green))
res2: TrafficLight = Red

scala> Enum[TrafficLight].pred(Red)
res3: TrafficLight = Yellow