Skip to content

Latest commit

 

History

History
59 lines (45 loc) · 2.35 KB

README.md

File metadata and controls

59 lines (45 loc) · 2.35 KB

eidos

Invariants functors and arrows with generics in shapeless

Converter

Converter is a type class that represents both of parsers and printers. We can construct parsers and printers by a single definition.

The following definition is a sample program using Converter.

import com.phenan.eidos._
import com.phenan.eidos.common.converter._
import com.phenan.eidos.syntax.converter._
import scala.language.higherKinds

sealed trait Hoge
case object Foo extends Hoge
case class Bar (n: Int, s: String) extends Hoge

object Test {
  def hoge [F[_]] (implicit F: Converter[F, Char]): F[Hoge] = union[Hoge] (
    keyword("foo")   *> struct[Foo.type](),
    keyword("bar: ") *> struct[Bar](integer, keyword(", ") *> javaIdentifier)
  )
}

union and struct is a combinator of Converter using generics in shapeless. They express composition of Converters following to algebraic data types. union is a parallel composition of Converters and it returns a Converter of the super type that is defined as sealed class or sealed trait. union takes a type that is the super type and it takes Converters for all the sub types as arguments. It returns the Converter of the given super type. Surprisingly, we do not need to write a conversion between the super type (Hoge in this example) and the sub types (Foo and Bar). Such conversion is automatically inferred by generics.

struct is a sequential composition of Converters and it returns a Converter of the composed data type that is defined as case class. struct takes a type that is the composed data type and it takes Converters for all argument types of the primary constructor of the data. For example, Bar takes two arguments, Int and String, so struct[Bar] takes two Converters of Int and String.

Converter is implemented as a tagless-final style, so we should declare which interpreter we want to use. This library provides PEGParser and StreamPrinter as an interpreter of Converter. The following program is a sample program that interprets Test.hoge.

 import com.phenan.eidos.data._
 
 val x = Test.hoge[PEGParser[Char, ?]].evalParser("bar: 123, hoge".toStream)
 // x : Some(Bar(123, "hoge"))
 
 val y = Test.hoge[StreamPrinter[Char, ?]].runPrinter(Bar(-456, "piyo"))
 // y : "bar: -456, piyo".toStream

Author

@phenan