So I've been trying to push my intuitions of functors to their limits by defining a higher order functor i.e. a, F that takes 1st order types as type argument, and functions and lifts functions on 1st order types to this higher context in scala something like
trait Functor1[F[_[_]] {
def hmap[X[_], Y[_]] : (X ~> Y) => F[X] => F[Y]
}
I've been trying to define some of the map derivable functions of the normal functor e.g.
trait Functor[F[_]] {
def map[A, B] : (A => B) => F[A] => F[B]
// there's a few more besides this that are map derivable
def distribute[A,B](fab: F[(A, B)]): (F[A], F[B])
}
but I can't write anything that type checks...
I'm just playing but I wonder if anyone else has been down this road that's smarter than me
can a higher order functor be defined in scala ? if not then in haskell ?
Not sure what are your goals, but this typechecks
import scala.language.higherKinds
trait Functor1[F[G[_]]]{
def hmap[X[_], Y[_]]:(X ~> Y) => F[X] => F[Y]
}
case class FId[Z,F[_]](f:F[Z])
implicit def Functor1Id[Z] = new Functor1[({type L[G[_]]=FId[Z,G]})#L]{
def hmap[X[_], Y[_]]:(X ~> Y) => FId[Z,X] => FId[Z,Y]= ???
}
(I added the Z parameter because I wanted to avoid existentials and I had to use the "type lambda" trick)
Do you want to define a map for a "functor of a functor"?
I think I did something similar (here called composition):
case class Comp[F[_],G[_],Z](unComp:F[G[Z]])
implicit def fcomp[F[_], G[_]](implicit ff:Functor[F], fg:Functor[G])=new Functor[({ type abs[A]=Comp[F,G,A]})#abs]{
def fmap[A,B](fga:Comp[F,G,A])(f: A => B):Comp[F,G,B]= Comp(ff.fmap(fga.unComp)(fg.fmap(_)(f)))
}
I've been toying with functors in scala-reggen but I don't think I'm the smart one, as I mainly did it by fumbling around (and checking Scalaz for inspiration)
/** Higher order functor */
trait HFunctor[F[_]] {
def ffmap[G[_]: Functor, A, B](f: A => B): F[G[A]] => F[G[B]]
def hfmap[G[_], H[_]](t: G ~> H): ({type λ[α] = F[G[α]]})#λ ~> ({type λ[α] = F[H[α]]})#λ
}
trait Functor[F[_]] { self =>
def fmap[A, B](f: A => B): F[A] => F[B]
// derived
def map[A, B](x: F[A])(f: A => B): F[B] = fmap(f)(x)
def strengthL[A, B]: A => F[B] => F[(A, B)] = a => f => fmap((x: B) => (a, x))(f)
def strengthR[A, B]: F[A] => B => F[(A, B)] = f => b => fmap((x: A) => (x, b))(f)
def compose[G[_]](implicit e: Functor[G]): Functor[({ type λ[α] = F[G[α]]})#λ] =
new Functor[({ type λ[α] = F[G[α]]})#λ] {
def F = self;
def G = e
def fmap[A, B](f: A => B) = F.fmap(G.fmap(f))
}
}
object Functor {
#inline def apply[F[_]: Functor]: Functor[F] = iev
}
trait Coyoneda[F[_], A] { co =>
type I
def fi: F[I]
def k: I => A
final def run(implicit F: Functor[F]): F[A] = F.fmap(k)(fi)
final def map[B](f: A => B): Coyoneda.Aux[F, B, I] =
Coyoneda(fi)(f compose k)
final def trans[G[_]](phi: F ~> G): Coyoneda[G, A] =
Coyoneda(phi(fi))(k)
}
object Coyoneda {
type Aux[F[_], A, B] = Coyoneda[F, A] { type I = B }
def apply[F[_], B, A](x: F[B])(f: B => A): Aux[F, A, B] =
new Coyoneda[F, A] {
type I = B
val fi = x
val k = f
}
implicit def coyonedaFunctor[F[_]]: Functor[({ type λ[α] = Coyoneda[F, α] })#λ] =
new Functor[({ type λ[α] = Coyoneda[F, α] })#λ] {
def fmap[A, B](f: A => B): Coyoneda[F, A] => Coyoneda[F, B] =
x => apply(x.fi)(f compose x.k)
}
implicit def coyonedaHFunctor: HFunctor[({ type λ[F[_]] = ({ type λ[α] = Coyoneda[F, α] })#λ })#λ] =
new HFunctor[({ type λ[F[_]] = ({ type λ[α] = Coyoneda[F, α] })#λ })#λ] {
def ffmap[G[_]: Functor, A, B](f: A => B): Coyoneda[G, A] => Coyoneda[G, B] = _.map(f)
def hfmap[F[_], G[_]](t: F ~> G): (({ type λ[α] = Coyoneda[F, α] })#λ ~> ({ type λ[α] = Coyoneda[G, α] })#λ) =
new (({ type λ[α] = Coyoneda[F, α] })#λ ~> ({ type λ[α] = Coyoneda[G, α] })#λ) {
def apply[A](x: Coyoneda[F, A]) = x.trans(t)
}
}
def liftCoyoneda[F[_], A](fa: F[A]): Coyoneda[F, A] = apply(fa)(x => x)
def lowerCoyoneda[F[_]: Functor, A](c: Coyoneda[F, A]): F[A] = c.run
}
Related
I was trying to apply typeclass pattern in scala and tried implementing Functor, Applicative and Monad typeclasses as follows
trait Functor[F[_]] {
def fmap[A, B] : (A => B) => F[A] => F[B]
}
object Functor {
def fmap[A, B, F[_]] (implicit ev: Functor[F]) = ev.fmap
}
trait Applicative[F[_]] {
def pure[A]: A => F[A]
def apply[A, B]: F[A => B] => F[A] => F[B]
}
object Applicative {
def pure[A, F[_]: Applicative]: A => F[A] = implicitly[Applicative[F]].pure
def apply[A, B, F[_]: Applicative]: F[A => B] => F[A] => F[B] = implicitly[Applicative[F]].apply
def liftA2[A, B, C, F[_]: Functor: Applicative]: (A => B => C) => F[A] => F[B] => F[C] =
f => fa => fb => implicitly[Applicative[F]].apply(implicitly[Functor[F]].fmap(f)(fa))(fb)
}
trait Monad[M[_]] {
def bind[A, B]: M[A] => (A => M[B]) => M[B]
def ret[A]: A => M[A]
}
object Monad {
def bind[A, B, M[_] :Monad]: M[A] => (A => M[B]) => M[B] = implicitly[Monad[M]].bind
def ret[A, M[_] :Monad]: A => M[A] = implicitly[Monad[M]].ret
}
sealed trait Maybe[A]
case class Some[A](value: A) extends Maybe[A]
case object None extends Maybe[Void] {
def apply[A]: Maybe[A] = None.asInstanceOf[Maybe[A]]
}
object Maybe {
def apply[A] (value: A): Maybe[A] = Some(value)
implicit object MaybeOps extends Functor[Maybe] with Applicative[Maybe] with Monad[Maybe] {
override def fmap[A, B]: (A => B) => Maybe[A] => Maybe[B] =
fn => ma => ma match {
case Some(a) => Maybe(fn(a))
case _ => None.apply
}
override def pure[A]: A => Maybe[A] = Some(_)
override def ret[A]: A => Maybe[A] = Some(_)
override def apply[A, B]: Maybe[A => B] => Maybe[A] => Maybe[B] = mab => ma => mab match {
case Some(f) => fmap(f)(ma)
case _ => None.apply
}
override def bind[A, B]: Maybe[A] => (A => Maybe[B]) => Maybe[B] = ma => f => ma match {
case Some(a) => f(a)
case _ => None.apply
}
}
}
And the consumer logic where I get to apply bind, fmap functions on Maybe datatype does not typecheck:
val a: Maybe[Int] = Maybe(10)
val p: Maybe[String] = bind.apply(Maybe(10))((i: Int) => Maybe(s"$i values"))
val q = fmap.apply(i => s"$i !!")(p)
println(p)
println(q)
The above code getting the error as
Error: (15, 29) type mismatch; found: String required: Nothing val q = fmap.apply(i => s"$i !!")(p)
I didn't want to extend the trait to make it work. Since the context-bounds specify the requirement of Monad typeclass to require an instance of Applicative in scope. Is there any clean way to support this in scala?
Editing the above code as per #Mateusz Kubuszok comments, worked fine for me.
trait Functor[F[_]] {
//def fmap[A, B] : (A => B) => F[A] => F[B]
def fmap[A, B](f: A => B, fa: F[A]): F[B]
}
object Functor {
//def fmap[A, B, F[_]] (implicit ev: Functor[F]) = ev.fmap
def fmap[A, B, F[_]](f: A => B, fa: F[A]) (implicit ev: Functor[F]) = ev.fmap(f, fa)
}
trait Applicative[F[_]] {
//def pure[A]: A => F[A]
def pure[A](a: A) : F[A]
//def apply[A, B]: F[A => B] => F[A] => F[B]
def appl[A, B](f: F[A=>B], fa: F[A]): F[B]
}
object Applicative {
//def pure[A, F[_]: Applicative]: A => F[A] = implicitly[Applicative[F]].pure
def pure[A, F[_]](a: A)(implicit ev: Applicative[F]) = ev.pure(a)
//def apply[A, B, F[_]: Applicative]: F[A => B] => F[A] => F[B] = implicitly[Applicative[F]].apply
def appl[A, B, F[_]] (f: F[A => B], fa: F[A])(implicit ev: Applicative[F]): F[B]=
ev.appl(f, fa)
def liftA2[A, B, C, F[_]: Functor: Applicative] (f: (A => B => C), fa: F[A], fb: F[B]): F[C] =
implicitly[Applicative[F]].appl(implicitly[Functor[F]].fmap(f, fa), fb)
}
trait Monad[M[_]] {
//def bind[A, B]: M[A] => (A => M[B]) => M[B]
def bind[A, B](ma: M[A], f: A => M[B]): M[B]
//def ret[A]: A => M[A]
def ret[A](a: A): M[A]
}
object Monad {
// def bind[A, B, M[_] :Monad]: M[A] => (A => M[B]) => M[B] = implicitly[Monad[M]].bind
def bind[A, B, M[_] :Monad](ma: M[A], f: (A => M[B])): M[B] = implicitly[Monad[M]].bind(ma, f)
//def ret[A, M[_] :Monad]: A => M[A] = implicitly[Monad[M]].ret
def ret[A, M[_] :Monad](a: A)(implicit ev: Monad[M]): M[A] = ev.ret(a)
}
sealed trait Maybe[A]
case class Some[A](value: A) extends Maybe[A]
case object None extends Maybe[Void] {
def apply[A]: Maybe[A] = None.asInstanceOf[Maybe[A]]
}
object Maybe {
def apply[A] (value: A): Maybe[A] = Some(value)
implicit object MaybeOps extends Functor[Maybe] with Applicative[Maybe] with Monad[Maybe] {
override def fmap[A, B](f: (A => B), ma: Maybe[A]): Maybe[B] =
ma match {
case Some(a) => Maybe(f(a))
case _ => None.apply
}
override def pure[A](a: A) : Maybe[A] = Some(a)
override def ret[A](a: A) : Maybe[A] = Some(a)
override def appl[A, B] (mab: Maybe[A => B], ma: Maybe[A]): Maybe[B] = mab match {
case Some(f) => fmap(f, ma)
case _ => None.apply
}
override def bind[A, B](ma: Maybe[A], f: (A => Maybe[B])) : Maybe[B] = ma match {
case Some(a) => f(a)
case _ => None.apply
}
}
}
import io.github.senthilganeshs.typeclass.Monad.bind
import io.github.senthilganeshs.typeclass.Functor.fmap
import io.github.senthilganeshs.types.Maybe
object Main {
def main(args: Array[String]): Unit = {
import io.github.senthilganeshs.types.Maybe._
val a: Maybe[Int] = Maybe(10)
val p: Maybe[String] = bind(Maybe(10), (i: Int) => Maybe(s"$i values"))
val q: Maybe[String] = fmap((i: String) => s"$i !!", p)
println(p)
println(q)
}
}
I'm using Scalaz as I'm loving a lot of aspects from Haskell's type class setup in the standard libraries. But exactly this is my current problem. I have a generic data structure with two generic parameters:
case class Parser[T,A](f: T => (T,A))
In Haskell I would implement the Alternative typeclass like this:
newtype Parser t a = Parser { runParser :: t -> (t,a) }
instance Alternative (Parser t) where
...
But how can I do something equivalent in Scala? As far as I know I can't do something like
object Parser {
implicit def ins_Alternative[T] = new Alternative[Parser[T]] {
// ...
}
}
Has anybody an idea how to do this? Thx in advance!
Update:
I've found this:
implicit def eitherMonad[L]: Traverse[Either[L, ?]] with MonadError[Either[L, ?], L] with BindRec[Either[L, ?]] with Cozip[Either[L, ?]] =
new Traverse[Either[L, ?]] with MonadError[Either[L, ?], L] with BindRec[Either[L, ?]] with Cozip[Either[L, ?]] {
def bind[A, B](fa: Either[L, A])(f: A => Either[L, B]) = fa match {
case Left(a) => Left(a)
case Right(b) => f(b)
}
// ...
}
in the Scalaz sources (https://github.com/scalaz/scalaz/blob/series/7.3.x/core/src/main/scala/scalaz/std/Either.scala).
According to this I guess I have to write something like
object Parser {
implicit def ins_Alternative[T] = new Alternative[Parser[T, ?]] {
// ...
}
}
which doesn't compile as the type ? is unknown.
I've found a solution.
implicit def ins_Alternative[T] = new Alternative[({type x[a] = Parser[T, a]})#x] {
override def empty[A]: Parser[T, A] = ???
override def plus[A](a: Parser[T, A], b: => Parser[T, A]): Parser[T, A] = ???
override def point[A](a: => A): Parser[T, A] = ???
override def ap[A, B](fa: => Parser[T, A])(f: => Parser[T, (A) => B]): Parser[T, B] = ???
}
So comonad.com has an interesting series of articles on working with applicatives and I've been trying to bring what I can to scala (for fun, and to learn). So, haskell defines FixF –
newtype FixF f a = FixF (f (FixF f) a)
it is written ,"FixF is of kind ((* -> *) -> * -> *) -> * -> *). It takes the fixpoint of a "second-order Functor" (a Functor that sends a Functor to another Functor, i.e. an endofunctor on the functor category of hask), to recover a standard "first order Functor" back out."
kinds classify types
* type A
* -> * type F[_]
* -> * -> * type F[_,_]
((* -> *) -> *) type F[F'[_]]
((* -> *) ->* -> *) type F[F'[_], A]
Now I've seen this
case class Fix[F[_]](out: F[Fix[F]])
// ((* -> *) -> * )
and this
case class BFixF[F[_,_], A](out: F[A, BFixF[F,A]])
So it's not the first one Fix (wrong kinds) Is it the second? I don't the think the kinds are right
BFixF :: ((* -> * -> * ) -> * -> *) ?
is it -
// edit as of this morning it is really not this
class FixF[F[_[_], _], A] :: ((* -> *) -> * -> *) -> *)
is it ?
case class FixF'[F[_], A](run: F[Fix[F, A]])
if so I'd love to see the proper definition and functor
case class FixF[F[_], A] (out: F[Fix[F, A]])
trait FixFFunctor[F[_]: Functor] extends Functor[({type l[x] = FixF[F, x]})#l] {
def map[A, B](f: A => B): FixF[F, A] => FixF[F, B] = ???
}
now bonus question, can someone define the applicative ?
This is a pretty cool question—I'd also read those posts, and had wondered about how terrifying a Scala implementation would look, but I never actually tried it. So I'm going to respond in some detail, but please note that the following is extremely off-the-cuff (it's Saturday morning, after all) and doesn't necessarily represent the cleanest way to do this in Scala.
It's probably best to start by defining some of the types from the first post in the series:
import scala.language.higherKinds
import scalaz._, Scalaz._
case class Const[M, A](mo: M)
sealed trait Sum[F[_], G[_], A]
object Sum {
def inL[F[_], G[_], A](l: F[A]): Sum[F, G, A] = InL(l)
def inR[F[_], G[_], A](r: G[A]): Sum[F, G, A] = InR(r)
}
case class InL[F[_], G[_], A](l: F[A]) extends Sum[F, G, A]
case class InR[F[_], G[_], A](r: G[A]) extends Sum[F, G, A]
And a couple more from the blog post itself:
case class Embed[F[_], A](out: A)
case class ProductF[F[_[_], _], G[_[_], _], B[_], A](f: F[B, A], g: G[B, A])
If you've worked through the above, you should have some sense of what FixF should look like:
case class FixF[F[f[_], _], A](out: F[({ type L[x] = FixF[F, x] })#L, A])
It turns out that this is a little too strict, though, so we'll use the following instead:
class FixF[F[f[_], _], A](v: => F[({ type L[x] = FixF[F, x] })#L, A]) {
lazy val out = v
override def toString = s"FixF($out)"
}
Now suppose we want to implement lists as a "second-order fixpoint of polynomial functors", as in the blog post. We can start by defining some useful aliases:
type UnitConst[x] = Const[Unit, x]
type UnitConstOr[F[_], x] = Sum[UnitConst, F, x]
type EmbedXUnitConstOr[F[_], x] = ProductF[Embed, UnitConstOr, F, x]
type MyList[x] = FixF[EmbedXUnitConstOr, x]
And now we can define the Scala version of the examples from the post:
val foo: MyList[String] = new FixF[EmbedXUnitConstOr, String](
ProductF[Embed, UnitConstOr, MyList, String](
Embed("foo"),
Sum.inL[UnitConst, MyList, String](Const())
)
)
val baz: MyList[String] = new FixF[EmbedXUnitConstOr, String](
ProductF[Embed, UnitConstOr, MyList, String](
Embed("baz"),
Sum.inL[UnitConst, MyList, String](Const())
)
)
val bar: MyList[String] = new FixF[EmbedXUnitConstOr, String](
ProductF[Embed, UnitConstOr, MyList, String](
Embed("bar"),
Sum.inR[UnitConst, MyList, String](baz)
)
)
This looks like what we'd expect given the Haskell implementation:
scala> println(foo)
FixF(ProductF(Embed(foo),InL(Const(()))))
scala> println(bar)
FixF(ProductF(Embed(bar),InR(FixF(ProductF(Embed(baz),InL(Const(())))))))
Now we need our type class instances. Most of these are pretty straightforward:
implicit def applicativeConst[M: Monoid]: Applicative[
({ type L[x] = Const[M, x] })#L
] = new Applicative[({ type L[x] = Const[M, x] })#L] {
def point[A](a: => A): Const[M, A] = Const(mzero[M])
def ap[A, B](fa: => Const[M, A])(f: => Const[M, A => B]): Const[M, B] =
Const(f.mo |+| fa.mo)
}
implicit def applicativeEmbed[F[_]]: Applicative[
({ type L[x] = Embed[F, x] })#L
] = new Applicative[({ type L[x] = Embed[F, x] })#L] {
def point[A](a: => A): Embed[F, A] = Embed(a)
def ap[A, B](fa: => Embed[F, A])(f: => Embed[F, A => B]): Embed[F, B] =
Embed(f.out(fa.out))
}
implicit def applicativeProductF[F[_[_], _], G[_[_], _], B[_]](implicit
fba: Applicative[({ type L[x] = F[B, x] })#L],
gba: Applicative[({ type L[x] = G[B, x] })#L]
): Applicative[({ type L[x] = ProductF[F, G, B, x] })#L] =
new Applicative[({ type L[x] = ProductF[F, G, B, x] })#L] {
def point[A](a: => A): ProductF[F, G, B, A] =
ProductF(fba.point(a), gba.point(a))
def ap[A, C](fa: => ProductF[F, G, B, A])(
f: => ProductF[F, G, B, A => C]
): ProductF[F, G, B, C] = ProductF(fba.ap(fa.f)(f.f), gba.ap(fa.g)(f.g))
}
Including the applicative instance for FixF itself:
implicit def applicativeFixF[F[_[_], _]](implicit
ffa: Applicative[({ type L[x] = F[({ type M[y] = FixF[F, y] })#M, x] })#L]
): Applicative[({ type L[x] = FixF[F, x] })#L] =
new Applicative[({ type L[x] = FixF[F, x] })#L] {
def point[A](a: => A): FixF[F, A] = new FixF(ffa.pure(a))
def ap[A, B](fa: => FixF[F, A])(f: => FixF[F, A => B]): FixF[F, B] =
new FixF(ffa.ap(fa.out)(f.out))
}
We'll also define the terminal transformation:
implicit def terminal[F[_], M: Monoid]: F ~> ({ type L[x] = Const[M, x] })#L =
new (F ~> ({ type L[x] = Const[M, x] })#L) {
def apply[A](fa: F[A]): Const[M, A] = Const(mzero[M])
}
But now we're in trouble. We really need some extra laziness in here, so we'll cheat a little:
def applicativeSum[F[_], G[_]](
fa: Applicative[F],
ga: => Applicative[G],
nt: G ~> F
): Applicative[({ type L[x] = Sum[F, G, x] })#L] =
new Applicative[({ type L[x] = Sum[F, G, x] })#L] {
def point[A](a: => A): Sum[F, G, A] = InR(ga.point(a))
def ap[A, B](x: => Sum[F, G, A])(f: => Sum[F, G, A => B]): Sum[F, G, B] =
(x, f) match {
case (InL(v), InL(f)) => InL(fa.ap(v)(f))
case (InR(v), InR(f)) => InR(ga.ap(v)(f))
case (InR(v), InL(f)) => InL(fa.ap(nt(v))(f))
case (InL(v), InR(f)) => InL(fa.ap(v)(nt(f)))
}
}
implicit def myListApplicative: Applicative[MyList] =
applicativeFixF[EmbedXUnitConstOr](
applicativeProductF[Embed, UnitConstOr, MyList](
applicativeEmbed[MyList],
applicativeSum[UnitConst, MyList](
applicativeConst[Unit],
myListApplicative,
terminal[MyList, Unit]
)
)
)
Maybe there's a way to get this to work with Scalaz 7's encoding of applicatives without the hack, but if there is I don't want to spend my Saturday afternoon figuring it out.
So that sucks, but at least now we can check our work:
scala> println((foo |#| bar)(_ ++ _))
FixF(ProductF(Embed(foobar),InL(Const(()))))
Which is exactly what we wanted.
Just by looking at the Haskell data type, I'd try the following class:
import scala.language.higherKinds
class FixF[F[_,_],A](val ffix: F[FixF[F,_],A]) extends AnyVal;
I'll try to expand the answer later when I learn more about FixF.
I occasionally hit code like this:
val things : List[A \/ B] = ???
val (as, bs) : (List[A], List[B]) = ??? //insert something to do this
or in my current case I want Map[A, B \/ C] => (Map[A, B], Map[A, C])
Is there a nice way to do this in the general case F[A \/ B] with appropriate restrictions on F? It looks vaguely like a variation on the theme of Unzip.
Here's how we deal with this for / but also Either and Validation, and not just for Lists, but other Foldable.
object Uncozip {
implicit val wtf = language.higherKinds
// Typeclass which covers sum types such as \/, Either, Validation
trait Sum2[F[_, _]] {
def cata[A, B, X](a: A ⇒ X, b: B ⇒ X)(fab: F[A, B]): X
}
implicit val sumEither: Sum2[Either] = new Sum2[Either] {
def cata[A, B, X](a: A ⇒ X, b: B ⇒ X)(fab: Either[A, B]): X = {
fab match {
case Left(l) ⇒ a(l)
case Right(r) ⇒ b(r)
}
}
}
implicit val sumEitherz: Sum2[\/] = new Sum2[\/] {
def cata[A, B, X](a: A ⇒ X, b: B ⇒ X)(fab: A \/ B): X = {
fab.fold(a(_), b(_))
}
}
implicit val sumValidation: Sum2[Validation] = new Sum2[Validation] {
def cata[A, B, X](a: A ⇒ X, b: B ⇒ X)(fab: A Validation B): X = {
fab.fold(a(_), b(_))
}
}
abstract class Uncozips[F[_], G[_, _], A, B](fab: F[G[A, B]]) {
def uncozip: (F[A], F[B])
}
implicit def uncozip[F[_]: Foldable, G[_, _], A, B](fab: F[G[A, B]])(implicit g: Sum2[G], mfa: ApplicativePlus[F], mfb: ApplicativePlus[F]): Uncozips[F, G, A, B] = new Uncozips[F, G, A, B](fab) {
def uncozip = {
implicitly[Foldable[F]].foldRight[G[A, B], (F[A], F[B])](fab, (mfa.empty, mfb.empty)) { (l, r) ⇒
g.cata[A, B, (F[A], F[B])]({ (a: A) ⇒ (mfa.plus(mfa.point(a), r._1), r._2) },
{ (b: B) ⇒ (r._1, mfa.plus(mfa.point(b), r._2)) })(l)
}
}
}
}
You can map things in to a list of (Option[A], Option[B]), unzip that list in to two lists, and then unite the resulting lists:
import scalaz._
import Scalaz._
val things: List[String \/ Int] = List("foo".left, 42.right)
val (strs, ints): (List[String], List[Int]) = things.
map { d => (d.swap.toOption, d.toOption) }. // List[(Option[String], Option[Int])]
unzip. // (List[Option[String]], List[Option[Int]])
bimap(_.unite, _.unite) // (List[String], List[Int])
This isn't particularly efficient due to traversing the list three times.
Here is one way (for lists):
val things : List[A \/ B] = ???
val (as, bs) = (things.map(_.swap.toList).join, things.map(_.toList).join)
And for a map:
val things: Map[String, String \/ Int] = ???
val (as, bs) = (things.mapValues(_.swap.toList).filterNot(e => e._2.isEmpty),
things.mapValues(_.toList).filterNot(e => e._2.isEmpty))
I'm having a hard time coming up with a way to generalize this over any F (I believe you would need instances of Monoid and Applicative for F).
I am trying to implement a function that would work on types that have a map and a flatMap method. I have already made it for Traversable, but this does not include Future and Option directly. So I have decided to go with my own interface, using a typeclass:
trait CanMap[A, M[_]] {
def map[B](l: M[A])(f: A => B): M[B]
def flatMap[B](l: M[A])(f: A => M[B]): M[B]
}
I already implemented this for Option:
implicit def canmapopt[A] = new CanMap[A, Option] {
def map[B](l: Option[A])(f: A => B): Option[B] = l.map(f)
def flatMap[B](l: Option[A])(f: A => Option[B]): Option[B] = l.flatMap(f)
}
and this one works very well. Now I wanted to implement it for any subtype of Traversable, I tried an implementation very close to the one for Option:
implicit def canmaptrav[A, B, T[B] <: Traversable[B]] = new CanMap[A, T] {
def map[B](l: T[A])(f: A => B): T[B] = l.map(f)
def flatMap[B](l: T[A])(f: A => T[B]): T[B] = l.flatMap(f)
}
but I get the error:
type mismatch; found : Traversable[B] required: T[B] Note: implicit method canmaptrav is not applicable here because it comes after the application point and it lacks an explicit result type
for the return type of l.map. I cannot understand why l.map(f) would return a Traversable and not the specific type T[B]. So I tried to explicitelly put the right type of CanBuildFrom in the context:
implicit def canmaptrav[A, B, T[B] <: Traversable[B]](implicit cbf: CanBuildFrom[T[A], B, T[B]]) = new CanMap[A, T] {
def map[B](l: T[A])(f: A => B): T[B] = l.map(f)
def flatMap[B](l: T[A])(f: A => T[B]): T[B] = l.flatMap(f)
}
The error persists.
Any idea where I went wrong? It might be obvious but I am getting confused with the generic type signatures I guess.
Update: Solution
First of all, as the answers pointed out, CanMap is mostly a Functor/Monad, so if you dare, you can use scalaz to implement this. However, if you are like me and want to try without it, here is the solution, based on the answer by Kipton Barros:
trait CanMap[A, B, M[_]] {
def map(l: M[A])(f: A => B): M[B]
def flatMap(l: M[A])(f: A => M[B]): M[B]
}
implicit def canmapopt[A, B] = new CanMap[A, B, Option] {
def map(l: Option[A])(f: A => B): Option[B] = l.map(f)
def flatMap(l: Option[A])(f: A => Option[B]): Option[B] = l.flatMap(f)
}
implicit def canmaptrav[A, B, M[+_]](implicit bf: CanBuildFrom[M[A], B, M[B]], ev: M[A] => TraversableLike[A, M[A]], eb: M[B] => TraversableLike[B, M[B]]) = new CanMap[A, B, M] {
def map(l: M[A])(f: (A) => B): M[B] = l.map(f)
def flatMap(l: M[A])(f: A => M[B]): M[B] = l.flatMap[B, M[B]] { (a: A) =>
f(a)
}
}
The trick is to use an implicit conversion M[A] => TraversableLike[A, M[A]] instead of trying to subtype Traversable.
The first problem is that there's a lot going on "under the hood" in the Traversable map method. It does a bit of work to return the most specific collection type, which is why you need CanBuildFrom. The second problem is that Option does not implement the Traversable interface, so its map method doesn't take a CanBuildFrom.
Here's the closest I could get,
import scala.collection.generic.CanBuildFrom
import collection.TraversableLike
trait CanMap[A, M[_]] {
def map[B](l: M[A])(f: A => B)(implicit bf: CanBuildFrom[M[A], B, M[B]]): M[B]
}
object Test {
// ugly hack to work around nonexistent CanBuildFrom for Option
implicit def optionBuilder[A, B]: CanBuildFrom[Option[A], B, Option[B]] = null
implicit def canmapopt[A] = new CanMap[A, Option] {
def map[B](l: Option[A])(f: A => B)(implicit bf: CanBuildFrom[Option[A], B, Option[B]]): Option[B] = l.map(f)
}
implicit def canmaptrav[A, M[_]](implicit ev: M[A] => TraversableLike[A, M[A]]) = new CanMap[A, M] {
def map[B](l: M[A])(f: (A) => B)(implicit bf: CanBuildFrom[M[A], B, M[B]]): M[B] = l.map(f)
}
// example usage
def mapper[A, B, M[_]](l: M[A])(f: A => B)(implicit cm: CanMap[A,M], bf: CanBuildFrom[M[A], B, M[B]]) = {
cm.map(l)(f)
}
mapper(List(1,2,3))(_ + 1) // List(2,3,4)
mapper(Some(2): Option[Int])(_ + 1) // Some(3)
// (cast to Option[Int] is needed to find the canmapopt implicit)
}
By the way, the implicit conversion to TraversableLike makes this also work with arrays,
mapper(Array(1,2,3))(_ + 1) // Array(2, 3, 4)
Firstly I tried your two failed attempts and didn't got much out of it. Then I decided to go simple and do my own CanMap implementation. I ended up with this:
def canmaptrav[A] = new CanMap[A, Traversable]{
def map[B](l: Traversable[A])(f: A => B): Traversable[B]= l.map(f)
def flatMap[B](l: Traversable[A])(f: A => Traversable[B]): Traversable[B] = l.flatMap(f)
}
Looking exactly the CanMap[_,Option]. Assuming the subtypes you are looking for is for use cases like this:
canmaptrav[Int].map(List(1,2,3,4))(_ + 1) //> res0: Traversable[Int] = List(2, 3, 4, 5)
canmaptrav[Int].map(Vector(1,2,3,4))(_ + 1) //> res1: Traversable[Int] = Vector(2, 3, 4, 5)
Now, if you want res1 and res0 types to be the concrete types (List, Vector) than the approach will have to indeed rely on the CanBuildFrom from.
BTW, you know that the CanMap is almost the Monad interface, right?
Scalaz already includes these typeclasses and they are called Monad and Functor. A short example:
// map
def foo[F[_] : Functor](xs: F[Int]) = xs.map(_ + 1)
scala> foo(List(1,2,3))
res2: List[Int] = List(2, 3, 4)
// flatMap
def flatten[M[_] : Monad](xs: M[M[Int]]) = xs.flatMap(identity)
scala> flatten(List(List(1,2,3)))
res3: List[Int] = List(1, 2, 3)
edit:
The functor instance for Future could look like this:
implicit object FutureFunctor extends Functor[Future] {
def map[A,B](fa: Future[A])(f: A => B) = fa.map(f)
}