diff --git a/algebird-util/src/main/scala/com/twitter/algebird/util/Algebras.scala b/algebird-util/src/main/scala/com/twitter/algebird/util/Algebras.scala deleted file mode 100644 index 5f16c9e56..000000000 --- a/algebird-util/src/main/scala/com/twitter/algebird/util/Algebras.scala +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2013 Twitter Inc. - * - * 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 com.twitter.algebird.util - -import com.twitter.algebird.{ Semigroup, Monoid, Group, Ring, Field } -import com.twitter.util.{Future, Try} - -object Algebras { - implicit def futureSemigroup[T:Semigroup]: Semigroup[Future[T]] = new FutureSemigroup[T] - implicit def futureMonoid[T:Monoid]: Monoid[Future[T]] = new FutureMonoid[T] - implicit def futureGroup[T:Group]: Group[Future[T]] = new FutureGroup[T] - implicit def futureRing[T:Ring]: Ring[Future[T]] = new FutureRing[T] - implicit def futureField[T:Field]: Field[Future[T]] = new FutureField[T] - - implicit def trySemigroup[T:Semigroup]: Semigroup[Try[T]] = new TrySemigroup[T] - implicit def tryMonoid[T:Monoid]: Monoid[Try[T]] = new TryMonoid[T] - implicit def tryGroup[T:Group]: Group[Try[T]] = new TryGroup[T] - implicit def tryRing[T:Ring]: Ring[Try[T]] = new TryRing[T] - implicit def tryField[T:Field]: Field[Try[T]] = new TryField[T] -} diff --git a/algebird-util/src/main/scala/com/twitter/algebird/util/FutureAlgebra.scala b/algebird-util/src/main/scala/com/twitter/algebird/util/FutureAlgebra.scala deleted file mode 100644 index 98fd66fdf..000000000 --- a/algebird-util/src/main/scala/com/twitter/algebird/util/FutureAlgebra.scala +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright 2013 Twitter Inc. - * - * 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 com.twitter.algebird.util - -import com.twitter.algebird.{ Semigroup, Monoid, Group, Ring, Field } -import com.twitter.util.Future - -/** - * Monoid and Semigroup on util.Future. - * - * @author Sam Ritchie - * @author Oscar Boykin - */ - -class FutureSemigroup[T: Semigroup] extends Semigroup[Future[T]] { - override def plus(l: Future[T], r: Future[T]): Future[T] = - for(lv <- l; rv <- r) yield Semigroup.plus(lv, rv) -} - -class FutureMonoid[T: Monoid] extends FutureSemigroup[T] with Monoid[Future[T]] { - override def zero = Future.value(Monoid.zero) -} - -class FutureGroup[T: Group] extends FutureMonoid[T] with Group[Future[T]] { - override def negate(v: Future[T]): Future[T] = v.map { implicitly[Group[T]].negate(_) } - override def minus(l: Future[T], r: Future[T]): Future[T] = - for(lv <- l; rv <- r) yield Group.minus(lv, rv) -} - -class FutureRing[T: Ring] extends FutureGroup[T] with Ring[Future[T]] { - override def one = Future.value(Ring.one) - override def times(l : Future[T], r: Future[T]) = - for(lv <- l; rv <- r) yield Ring.times(lv, rv) -} - -class FutureField[T: Field] extends FutureRing[T] with Field[Future[T]] { - override def inverse(v: Future[T]) = v.map { implicitly[Field[T]].inverse(_) } - override def div(l : Future[T], r: Future[T]) = - for(lv <- l; rv <- r) yield Field.div(lv, rv) -} diff --git a/algebird-util/src/main/scala/com/twitter/algebird/util/TryAlgebra.scala b/algebird-util/src/main/scala/com/twitter/algebird/util/TryAlgebra.scala deleted file mode 100644 index 670ac0ff3..000000000 --- a/algebird-util/src/main/scala/com/twitter/algebird/util/TryAlgebra.scala +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright 2013 Twitter Inc. - * - * 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 com.twitter.algebird.util - -import com.twitter.algebird.{ Semigroup, Monoid, Group, Ring, Field } -import com.twitter.util.{Try, Return, Throw} - -/** - * Monoid and Semigroup on util.Try. - * - * @author Sam Ritchie - * @author Oscar Boykin - */ - -// Clearly all these are generalizations of a Monad pattern with a single value: - -class TrySemigroup[T: Semigroup] extends Semigroup[Try[T]] { - override def plus(l: Try[T], r: Try[T]): Try[T] = - for(lv <- l; rv <- r) yield Semigroup.plus(lv, rv) -} - -class TryMonoid[T: Monoid] extends TrySemigroup[T] with Monoid[Try[T]] { - override def zero = Return(Monoid.zero) -} - -class TryGroup[T: Group] extends TryMonoid[T] with Group[Try[T]] { - override def negate(v: Try[T]): Try[T] = v.map { implicitly[Group[T]].negate(_) } - override def minus(l: Try[T], r: Try[T]): Try[T] = - for(lv <- l; rv <- r) yield Group.minus(lv, rv) -} - -class TryRing[T: Ring] extends TryGroup[T] with Ring[Try[T]] { - override def one = Return(Ring.one) - override def times(l : Try[T], r: Try[T]) = - for(lv <- l; rv <- r) yield Ring.times(lv, rv) -} - -class TryField[T: Field] extends TryRing[T] with Field[Try[T]] { - override def inverse(v: Try[T]) = v.map { implicitly[Field[T]].inverse(_) } - override def div(l : Try[T], r: Try[T]) = - for(lv <- l; rv <- r) yield Field.div(lv, rv) -} diff --git a/algebird-util/src/main/scala/com/twitter/algebird/util/UtilAlgebras.scala b/algebird-util/src/main/scala/com/twitter/algebird/util/UtilAlgebras.scala new file mode 100644 index 000000000..f2359582f --- /dev/null +++ b/algebird-util/src/main/scala/com/twitter/algebird/util/UtilAlgebras.scala @@ -0,0 +1,43 @@ +/* + * Copyright 2013 Twitter Inc. + * + * 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 com.twitter.algebird.util + +import com.twitter.algebird._ +import com.twitter.util.{ Future, Return, Try } + +object UtilAlgebras { + implicit val futureMonad: Monad[Future] = new Monad[Future] { + def apply[T](v: T) = Future.value(v); + def flatMap[T, U](m: Future[T])(fn: T => Future[U]) = m.flatMap(fn) + } + implicit val tryMonad: Monad[Try] = new Monad[Try] { + def apply[T](v: T) = Return(v); + def flatMap[T,U](m: Try[T])(fn: T => Try[U]) = m.flatMap(fn) + } + + implicit def futureSemigroup[T:Semigroup]: Semigroup[Future[T]] = new MonadSemigroup[T, Future] + implicit def futureMonoid[T:Monoid]: Monoid[Future[T]] = new MonadMonoid[T, Future] + implicit def futureGroup[T:Group]: Group[Future[T]] = new MonadGroup[T, Future] + implicit def futureRing[T:Ring]: Ring[Future[T]] = new MonadRing[T, Future] + implicit def futureField[T:Field]: Field[Future[T]] = new MonadField[T, Future] + + implicit def trySemigroup[T:Semigroup]: Semigroup[Try[T]] = new MonadSemigroup[T, Try] + implicit def tryMonoid[T:Monoid]: Monoid[Try[T]] = new MonadMonoid[T, Try] + implicit def tryGroup[T:Group]: Group[Try[T]] = new MonadGroup[T, Try] + implicit def tryRing[T:Ring]: Ring[Try[T]] = new MonadRing[T, Try] + implicit def tryField[T:Field]: Field[Try[T]] = new MonadField[T, Try] +} diff --git a/algebird-util/src/test/scala/com/twitter/algebird/util/UtilAlgebraProperties.scala b/algebird-util/src/test/scala/com/twitter/algebird/util/UtilAlgebraProperties.scala new file mode 100644 index 000000000..3155b522d --- /dev/null +++ b/algebird-util/src/test/scala/com/twitter/algebird/util/UtilAlgebraProperties.scala @@ -0,0 +1,47 @@ +/* + * Copyright 2013 Twitter Inc. + * + * 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 com.twitter.algebird.util + +import com.twitter.algebird.MonadLaws.monadLaws +import com.twitter.util.{ Future, Throw, Return, Try } +import org.scalacheck.{ Arbitrary, Properties } + +import Arbitrary.arbitrary + +object UtilAlgebraProperties extends Properties("UtilAlgebras") { + import UtilAlgebras._ + + def toOption[T](f: Future[T]): Option[T] = + if (f.isReturn) Some(f.get) else None + + implicit def futureA[T: Arbitrary]: Arbitrary[Future[T]] = + Arbitrary { + arbitrary[T].map { l => Future.value(l) } | + Future.exception(new RuntimeException("fail!")) + } + + implicit def returnA[T: Arbitrary]: Arbitrary[Try[T]] = + Arbitrary { + arbitrary[T].map { l => Return(l) } | + Throw(new RuntimeException("fail!")) + } + + property("futureMonad") = monadLaws[Future, Int, String, Long] { (f1, f2) => + toOption(f1) == toOption(f2) + } + property("tryMonad") = monadLaws[Try, Int, String, Long]() +} diff --git a/project/Build.scala b/project/Build.scala index e56c7e505..d68ca253a 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -66,7 +66,8 @@ object AlgebirdBuild extends Build { ).settings( test := { } ).aggregate(algebirdTest, - algebirdCore) + algebirdCore, + algebirdUtil) lazy val algebirdCore = Project( id = "algebird-core", @@ -89,4 +90,14 @@ object AlgebirdBuild extends Build { "org.scala-tools.testing" %% "specs" % "1.6.9" ) ).dependsOn(algebirdCore) + + lazy val algebirdUtil = Project( + id = "algebird-util", + base = file("algebird-util"), + settings = sharedSettings + ).settings( + name := "algebird-util", + resolvers += "Twitter Maven" at "http://maven.twttr.com", + libraryDependencies += "com.twitter" % "util-core" % "5.3.15" + ).dependsOn(algebirdCore, algebirdTest % "compile->test") }