paradoxical-io / scala-tiny-types   1.5.0

MIT License GitHub

Tiny type generator for scala

Scala versions: 2.11 2.10

scala-tiny-types

This is a small console app to create scala based "tiny types".

Why tiny types? This way you pay no penalty in adding more domain specific information to your project. For example, a first name isn't the same as a last name. And your address isn't the same as your age, so why would you represent them the same?

To install run the install script.

Run tiny-types and give it the path to the defintions file (which is just a comma sepearated case class name followed by target type (Fully qualified)), and the output package type of the form "com.foo.bar". It will write two files into "src/main/scala/com/foo/bar" being the case class tiny definitions as well as the implicit conversions.

Install

"io.paradoxical" %% "tiny-types" % "1.1"

Usage

tiny-types 1.0
Usage: tiny-types [options]

  -d <value> | --definitionsFile <value>
        The json definitions file

TypeTagging vs Case Classes

There are two camps of tiny type aliasing, one is case class wrapping (which is the default) and the other is type tagging.

Type tags are inspired by this blog post: https://coderwall.com/p/l-plmq/adding-semantic-to-base-types-parameters-in-scala

Example case classes

As an example, given the following input file

[
  {
    "package": "io.paradoxical.scala.tiny.data",
    "folder": "src/test/scala",
    "tiny": {
      "bar": "String",
      "foo": "String",
      "bizBaz": "Int",
      "Data" : "java.util.UUID"
    }
  }
]

We'll get

package io.paradoxical.scala.tiny.data

case class bar(data : String) extends AnyVal
case class foo(data : String) extends AnyVal
case class bizBaz(data : Int) extends AnyVal
case class Data(data : java.util.UUID) extends AnyVal

object Conversions{
    implicit def convertbar(i : bar) : String = i.data
    implicit def convertfoo(i : foo) : String = i.data
    implicit def convertbizBaz(i : bizBaz) : Int = i.data
    implicit def convertData(i : Data) : java.util.UUID = i.data
}

Example type tagging

With the following input file

[
  {
    "package": "io.paradoxical.scala.tiny.data.typetag2",
    "folder": "src/test/scala",
    "format": "TypeTag",
    "tiny": {
      "workId": "String",
      "funId": "Int",
      "barId": "Int",
      "tableId": "java.util.UUID"
    }
  }
]

We'll get

package io.paradoxical.scala.tiny.data.typetag2
object TinyType {
  type Tagged[U] = { type Tag = U }

  trait TinyWorkId
  type workId = String with Tagged[TinyWorkId]
  def WorkId(rawType: String): workId = rawType.asInstanceOf[workId]

  trait TinyFunId
  type funId = Int with Tagged[TinyFunId]
  def FunId(rawType: Int): funId = rawType.asInstanceOf[funId]

  trait TinyBarId
  type barId = Int with Tagged[TinyBarId]
  def BarId(rawType: Int): barId = rawType.asInstanceOf[barId]

  trait TinyTableId
  type tableId = java.util.UUID with Tagged[TinyTableId]
  def TableId(rawType: java.util.UUID): tableId = rawType.asInstanceOf[tableId]
}

Which can be used now:

import io.paradoxical.scala.tiny.data.typetag2.TinyType._

val funId: funId = FunId(1)
val barId: barId = BarId(1)

acceptsAlias(FunId(1))
//  acceptsAlias(barId) [ fails because barId is not a fooId even though they are both int ]
acceptsAlias(funId)

def acceptsAlias(funId: funId) = funId

Zsh completion

#compdef tiny-types

local arguments

arguments=(
'-d[Json tiny types descriptor]:descriptor file:_files'
)

_arguments -s $arguments

Drop this into your zsh functions folder as _tiny-types and you're good to go!