Skip to content

Instantly share code, notes, and snippets.

@beezee
Created October 8, 2018 14:19
Show Gist options
  • Save beezee/533285b2123fb7cf6fd77456f061853e to your computer and use it in GitHub Desktop.
Save beezee/533285b2123fb7cf6fd77456f061853e to your computer and use it in GitHub Desktop.
import scalaz.{Alt, Apply, ApplicativePlus, Arrow, Choice, Decidable, Divide, Semigroup}
object Derive {
implicit def ArrowInstanceCovariant[F[_, _], From](implicit A: Arrow[F]): Apply[F[From, ?]] = new Apply[F[From, ?]] {
def map[A, B](fa: F[From, A])(f: A => B): F[From, B] = A.compose(A.arr(f), fa)
def ap[A,B](fa: => F[From, A])(f: => F[From, A => B]): F[From, B] =
A.mapsnd(A.combine(f, fa))(t => t._1(t._2))
}
implicit def ArrowChoiceInstance[F[_, _], To](implicit A: Arrow[F], C: Choice[F]): Decidable[F[?, To]] = new Decidable[F[?, To]] {
def choose2[Z, A1, A2](a1: =>F[A1, To], a2: =>F[A2, To])(f: Z => (A1 \/ A2)): F[Z, To] =
A.mapfst(C.choice(a1, a2))(f)
}
implicit def ArrowInstance[F[_, _], To](A: Arrow[F], S: Semigroup[To]): Divide[F[?, To]] = new Divide[F[?, To]] {
def contramap[A, B](r: F[A, To])(f: B => A): F[B, To] = A.mapfst(r)(f)
def divide2[A1, A2, Z](a1: =>F[A1, To], a2: =>F[A2, To])(f: Z => (A1, A2)): F[Z, To] =
A.compose(A.arr((t: (To, To)) => S.append(t._1, t._2)), A.compose(A.splitA(a1, a2), A.arr(f)))
}
implicit def altPlus[F[_]](implicit AP: ApplicativePlus[F]): Alt[F] = new Alt[F] {
def point[A](a: => A): F[A] = AP.point(a)
def ap[A, B](fa: => F[A])(f: => F[A => B]): F[B] = AP.ap(fa)(f)
def alt[A](a1: =>F[A], a2: =>F[A]): F[A] = AP.plus(a1, a2)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment