Skip to content

Commit

Permalink
Add inject syntax
Browse files Browse the repository at this point in the history
  • Loading branch information
andyscott committed Nov 5, 2017
1 parent 0f15d38 commit c4a68d8
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 23 deletions.
36 changes: 17 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,4 @@

[comment]: # (Start Badges)

[![Build Status](https://travis-ci.org/frees-io/iota.svg?branch=master)](https://travis-ci.org/frees-io/iota) [![Maven Central](https://img.shields.io/badge/maven%20central-0.3.1-green.svg)](https://oss.sonatype.org/#nexus-search;gav~io.frees~iota*) [![License](https://img.shields.io/badge/license-Apache%202-blue.svg)](https://raw.githubusercontent.com/frees-io/iota/master/LICENSE) [![Latest version](https://img.shields.io/badge/iota-0.3.1-green.svg)](https://index.scala-lang.org/frees-io/iota) [![Scala.js](http://scala-js.org/assets/badges/scalajs-0.6.20.svg)](http://scala-js.org) [![GitHub Issues](https://img.shields.io/github/issues/frees-io/iota.svg)](https://github.com/frees-io/iota/issues)

[comment]: # (End Badges)

# Iota

## Introduction
Expand Down Expand Up @@ -103,19 +97,23 @@ def processFoo(foo: Foo): String = foo match {
case DoubleFoo(double) => s"double: $double"
}

val foo0: Foo = IntFoo.inj(100)
val foo1: Foo = StringFoo.inj("hello world")
val foo2: Foo = DoubleFoo.inj(47.6062)
import iota.syntax.all._

val foo0: Foo = 100.inject[Foo]
val foo1: Foo = "hello world".inject[Foo]
val foo2: Foo = 47.6062.inject[Foo]


```
```scala
processFoo(foo0)
// res11: String = int: 100
// res14: String = int: 100

processFoo(foo1)
// res12: String = string: hello world
// res15: String = string: hello world

processFoo(foo2)
// res13: String = double: 47.6062
// res16: String = double: 47.6062
```

*coproduct of type constructors*
Expand All @@ -137,13 +135,13 @@ val bar2: Bar[String] = SeqBar.inj(Seq("a", "b", "c"))
```
```scala
processBar(bar0)
// res16: String = option: Some(200)
// res19: String = option: Some(200)

processBar(bar1)
// res17: String = list: List(hello, world)
// res20: String = list: List(hello, world)

processBar(bar2)
// res18: String = seq: List(a, b, c)
// res21: String = seq: List(a, b, c)
```

## Fast Interpreters
Expand Down Expand Up @@ -204,7 +202,7 @@ import iota.debug.options.ShowTrees
// import iota.debug.options.ShowTrees

CopK.FunctionK.of[Algebra, Future](evalOrderOp, evalPriceOp, evalUserOp)
// <console>:32: {
// <console>:35: {
// class CopKFunctionK$macro$4 extends _root_.iota.internal.FastFunctionK[Algebra, Future] {
// private[this] val arr0 = evalUserOp.asInstanceOf[_root_.cats.arrow.FunctionK[Any, scala.concurrent.Future]];
// private[this] val arr1 = evalOrderOp.asInstanceOf[_root_.cats.arrow.FunctionK[Any, scala.concurrent.Future]];
Expand All @@ -213,8 +211,8 @@ CopK.FunctionK.of[Algebra, Future](evalOrderOp, evalPriceOp, evalUserOp)
// case 0 => arr0(η$.value)
// case 1 => arr1(η$.value)
// case 2 => arr2(η$.value)
// case (i @ _) => throw new _root_.java.lang.Exception(StringContext("iota internal error: index ").s().+(i).+(" out of bounds for ").+(this)...
// res33: iota.internal.FastFunctionK[Algebra,scala.concurrent.Future] = FastFunctionK[Algebra, scala.concurrent.Future]<<generated>>
// case (i @ _) => throw new _root_.java.lang.Exception(StringContext("iota internal error: index ").s().+(i).+(" out of bounds for ")...
// res36: iota.internal.FastFunctionK[Algebra,scala.concurrent.Future] = FastFunctionK[Algebra, scala.concurrent.Future]<<generated>>
```

#### Is it actually faster?
Expand Down Expand Up @@ -252,4 +250,4 @@ Copyright (C) 2016-2017 47 Degrees. <http://47deg.com>

[comment]: # (End Copyright)

[free example]: modules/tests/src/test/scala/iotatests/FreeCopKTests.scala
[free example]: modules/tests/src/test/scala/iotatests/FreeCopKTests.scala
21 changes: 21 additions & 0 deletions modules/core/src/main/scala/iota/syntax/helpers.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package iota //#=cats
package iotaz //#=scalaz
package syntax

final class InjectOps[A](val a: A) extends AnyVal {
def inject[B <: Cop[_]](implicit ev: Cop.Inject[A, B]): B =
ev.inj(a)
}

trait InjectSyntax {
implicit def toInjectOps[A](a: A): InjectOps[A] = new InjectOps(a)
}

final class InjectKOps[F[_], A](val fa: F[A]) extends AnyVal {
def injectK[G[_] <: CopK[_, _]](implicit ev: CopK.Inject[F, G]): G[A] =
ev.inj(fa)
}

trait InjectKSyntax {
implicit def toInjectKOps[F[_], A](fa: F[A]): InjectKOps[F, A] = new InjectKOps(fa)
}
11 changes: 11 additions & 0 deletions modules/core/src/main/scala/iota/syntax/package.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package iota //#=cats
package iotaz //#=scalaz

package object syntax {
object inject extends InjectSyntax
object injectK extends InjectKSyntax

object all
extends InjectSyntax
with InjectKSyntax
}
47 changes: 47 additions & 0 deletions modules/examples/src/main/scala/iotaexamples/InjectSyntax.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* Copyright 2016-2017 47 Degrees, LLC. <http://www.47deg.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package iotaexamples

import iota._
import iota.syntax.all._

import scala.Predef._

object InjectSyntax extends App {
import TList.::
import TListK.:::

object Luna
object Mabel
object Finn
object Cinder
object Bridger

type Dog = Cop[
Luna.type :: Mabel.type :: Finn.type :: Cinder.type :: Bridger.type :: TNil]

val dog0: Dog = Luna.inject[Dog]
val dog1: Dog = Finn.inject[Dog]

println(dog0)
println(dog1)

type Wat[A] = CopK[List ::: Option ::: TNilK, A]

val res0: Wat[String] = List("hello", "world").injectK[Wat]
val res1: Wat[Int] = Option(1).injectK[Wat]
}
12 changes: 8 additions & 4 deletions modules/readme/src/main/tut/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,13 @@ def processFoo(foo: Foo): String = foo match {
case DoubleFoo(double) => s"double: $double"
}
val foo0: Foo = IntFoo.inj(100)
val foo1: Foo = StringFoo.inj("hello world")
val foo2: Foo = DoubleFoo.inj(47.6062)
import iota.syntax.all._
val foo0: Foo = 100.inject[Foo]
val foo1: Foo = "hello world".inject[Foo]
val foo2: Foo = 47.6062.inject[Foo]
```
```tut:book
processFoo(foo0)
Expand Down Expand Up @@ -229,4 +233,4 @@ Copyright (C) 2016-2017 47 Degrees. <http://47deg.com>

[comment]: # (End Copyright)

[free example]: modules/tests/src/test/scala/iotatests/FreeCopKTests.scala
[free example]: modules/tests/src/test/scala/iotatests/FreeCopKTests.scala

0 comments on commit c4a68d8

Please sign in to comment.