-
Notifications
You must be signed in to change notification settings - Fork 75
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add option to use underscore symbol
_
instead of *
to define anon…
…ymous type lambdas (#188)
- Loading branch information
Showing
11 changed files
with
330 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,6 @@ jobs: | |
matrix: | ||
os: [ubuntu-latest] | ||
scala: | ||
- 2.10.7 | ||
- 2.11.12 | ||
- 2.12.8 | ||
- 2.12.9 | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package underscores | ||
|
||
trait Functor[M[_]] { | ||
def fmap[A, B](fa: M[A])(f: A => B): M[B] | ||
} | ||
|
||
class EitherRightFunctor[L] extends Functor[Either[L, _]] { | ||
def fmap[A, B](fa: Either[L, A])(f: A => B): Either[L, B] = | ||
fa match { | ||
case Right(a) => Right(f(a)) | ||
case Left(l) => Left(l) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
package underscores | ||
|
||
trait ~~>[A[_[_]], B[_[_]]] { | ||
def apply[X[_]](a: A[X]): B[X] | ||
} | ||
|
||
trait Bifunctor[F[_[_[_]], _[_[_]]]] { | ||
def bimap[A[_[_]], B[_[_]], C[_[_]], D[_[_]]](fab: F[A, B])(f: A ~~> C, g: B ~~> D): F[C, D] | ||
} | ||
|
||
final case class Coproduct[A[_[_]], B[_[_]], X[_]](run: Either[A[X], B[X]]) | ||
|
||
object Coproduct { | ||
def coproductBifunctor[X[_]]: Bifunctor[Coproduct[_[_[_]], _[_[_]], X]] = | ||
new Bifunctor[Coproduct[_[_[_]], _[_[_]], X]] { | ||
def bimap[A[_[_]], B[_[_]], C[_[_]], D[_[_]]](abx: Coproduct[A, B, X])(f: A ~~> C, g: B ~~> D): Coproduct[C, D, X] = | ||
abx.run match { | ||
case Left(ax) => Coproduct(Left(f(ax))) | ||
case Right(bx) => Coproduct(Right(g(bx))) | ||
} | ||
} | ||
def test[X[_]]: Bifunctor[({ type L[F[_[_]], G[_[_]]] = Coproduct[F, G, X] })#L] = coproductBifunctor[X] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
package underscores | ||
|
||
// // From https://github.com/non/kind-projector/issues/20 | ||
// import scala.language.higherKinds | ||
|
||
object KindProjectorWarnings { | ||
trait Foo[F[_], A] | ||
trait Bar[A, B] | ||
|
||
def f[G[_]]: Unit = () | ||
|
||
f[Foo[Bar[Int, _], _]] // shadowing warning | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
package underscores | ||
|
||
trait ~>[-F[_], +G[_]] { | ||
def apply[A](x: F[A]): G[A] | ||
} | ||
trait ~>>[-F[_], +G[_]] { | ||
def dingo[B](x: F[B]): G[B] | ||
} | ||
final case class Const[A, B](getConst: A) | ||
|
||
class PolyLambdas { | ||
type ToSelf[F[_]] = F ~> F | ||
|
||
val kf1 = Lambda[Option ~> Vector](_.iterator.toVector) | ||
|
||
val kf2 = λ[Vector ~> Option] { | ||
case Vector(x) => Some(x) | ||
case _ => None | ||
} | ||
|
||
val kf3 = λ[ToSelf[Vector]](_.reverse) | ||
|
||
val kf4 = λ[Option ~>> Option].dingo(_ flatMap (_ => None)) | ||
|
||
val kf5 = λ[Map[_, Int] ~> Map[_, Long]](_.map { case (k, v) => (k, v.toLong) }.toMap) | ||
|
||
val kf6 = λ[ToSelf[Map[_, Int]]](_.map { case (k, v) => (k, v * 2) }.toMap) | ||
|
||
implicit class FGOps[F[_], A](x: F[A]) { | ||
def ntMap[G[_]](kf: F ~> G): G[A] = kf(x) | ||
} | ||
|
||
// Scala won't infer the unary type constructor alias from a | ||
// tuple. I'm not sure how it even could, so we'll let it slide. | ||
type PairWithInt[A] = (A, Int) | ||
def mkPair[A](x: A, y: Int): PairWithInt[A] = x -> y | ||
val pairMap = λ[ToSelf[PairWithInt]] { case (k, v) => (k, v * 2) } | ||
val tupleTakeFirst = λ[λ[A => (A, Int)] ~> List](x => List(x._1)) | ||
|
||
// All these formulations should be equivalent. | ||
def const1[A] = λ[ToSelf[Const[A, _]]](x => x) | ||
def const2[A] : ToSelf[Const[A, _]] = λ[Const[A, _] ~> Const[A, _]](x => x) | ||
def const3[A] : Const[A, _] ~> Const[A, _] = λ[ToSelf[Const[A, _]]](x => x) | ||
def const4[A] = λ[Const[A, _] ~> Const[A, _]](x => x) | ||
def const5[A] : ToSelf[Const[A, _]] = λ[ToSelf[λ[B => Const[A, B]]]](x => x) | ||
def const6[A] : Const[A, _] ~> Const[A, _] = λ[ToSelf[λ[B => Const[A, B]]]](x => x) | ||
|
||
@org.junit.Test | ||
def polylambda(): Unit = { | ||
assert(kf1(None) == Vector()) | ||
assert(kf1(Some("a")) == Vector("a")) | ||
assert(kf1(Some(5d)) == Vector(5d)) | ||
assert(kf2(Vector(5)) == Some(5)) | ||
assert(kf3(Vector(1, 2)) == Vector(2, 1)) | ||
assert(kf4.dingo(Some(5)) == None) | ||
assert(kf5(Map("a" -> 5)) == Map("a" -> 5)) | ||
assert(kf6(Map("a" -> 5)) == Map("a" -> 10)) | ||
|
||
assert((mkPair("a", 1) ntMap pairMap) == ("a" -> 2)) | ||
assert((mkPair(Some(true), 1) ntMap pairMap) == (Some(true) -> 2)) | ||
|
||
assert(mkPair('a', 1).ntMap(tupleTakeFirst) == List('a')) | ||
// flatten works, whereas it would be a static error in the | ||
// line above. That's pretty poly! | ||
assert(mkPair(Some(true), 1).ntMap(tupleTakeFirst).flatten == List(true)) | ||
} | ||
} |
Oops, something went wrong.