So just to contextualize this for the uninitiated (not necessarily excluding myself), functors are a grade A context/mapping abstraction. In Scalanese:
trait FunctorStr[F[_]] {
def map[A, B](f: A => B): F[A] => F[B]
}
lots of things are functors blah blah, now if you are interested in generic programming and DSL crafting as a design pattern functors come up a lot. So, in keeping with the theme of extending intuition, lets get down to it. Half way through comonad.com's Rotten Bananas we are introduced to class Cata
given in Haskellese:
class Cata f t | t -> f where
cata:: (f a -> a) -> t -> a
now this Class is near the beginning of the fun for us the reader, but for me the scala implementer ...
Cata is the beginning of our trouble
this functional dependency t -> f does it mean "f is uniquely determined by t" ?
if you asked Miles Sabin in 2011
the fundep pattern is totally realizable in scala and put simply involves initiating an implicit search via an implicit parameter section and witnessing types to resolve the search but I can't say I get it so well as to instantly translate t -> f to scala
I'm seeing it in scala as something like
abstract class Cata[F[_], T](implicit e: ???) {
def cata[A]: (F[A] => A) => T => A
}
trait CataFunctor[F[_]] extends FunctorStr[({type l[x] = Cata[F, x]})#l] {
def map[A, B](f: A => B): Cata[F, A] => Cata[F, B]
}
Quoting the article:
given cata and fmap one can go through and build up a whole host of
other recursion schemes, paramorphisms, zygomorphisms, histomorphisms,
generalized catamorphisms, ...; the menagerie is quite forbidding and
these can be used to tear apart covariant functors with reckless
abandon. With the power of a paramorphism you rederive the notion of
general recursion, and so you can basically write any recursive
function you want. (On the coalgebra side of the house there are
anamorphisms, apomorphisms, and all sorts of other beasts for
effectively generating covariant functors)
This is the power I seek.
I'm trying to work this out and would really like some help? Now I've the InvariantFunctor Implemented in scalaz so I know that this isn't a fools errand.
Can I get a nudge in the right direction here? I'm down for as much detail as possible so like, go nuts.
Reading the linked post it looks like you need:
trait CataDep[T, F[_]]
abstract class Cata[F[_], T](implicit e: CataDep[T, F]) {
def cata[A]: (F[A] => A) => T => A
}
Related
What's the point of using a typeclass over inheritance?
This is a function that uses the Monad typeclass by a context bound:
def f[A : Monad](x:A) = ???
( Yeah, we get flatMap method now)
This, however, uses inheritance with a subtype bound:
def f[A <: Monad](x:A) = ???
f(x) // where x is a CatsList which implements Monad trait.
( We also get flatMap method now.)
Don't both achieve the same thing?
Typeclasses are more flexible. In particular, it's possible to retrofit a typeclass to an existing type easily. To do this with inheritance, you would need to use the adapter pattern, which can get cumbersome when you have multiple traits.
For example, suppose you had two libraries which added the traits Measurable and Functor, respectively, using inheritance:
trait Measurable {
def length: Int
}
trait Functor[A] {
def map[B](f: A => B): Functor[B]
}
The first library helpfully defined an adapter for List => Measurable:
class ListIsMeasurable(ls: List[_]) extends Measurable {
def length = ls.length
}
And the second library did the same for List => Functor. Now we want to write a function that takes things that have both length and map methods:
def foo(x: Measurable with Functor) = ???
Of course, we should hope to be able to pass it a List. However, our adapters are useless here, and we have to write yet another adapter to make List conform to Measurable with Functor. In general, if you have n interfaces that might apply to List, you have 2^n possible adapters. On the other hand, if we had used typeclasses, there would have been no need for the extra boilerplate of a third typeclass instance:
def foo[A : Measurable : Functor](a: A) = ???
What you're saying is possible for the simplest cases, but type classes can give you much better flexibility in a lot of cases.
Take for example the Monoid type class:
trait Monoid[A] {
def empty: A
def combine(x: A, y: A): A
}
If you try to express the empty function with inheritance, you'll see it is pretty much impossible. That is because type classes operate on types rather than individual class instances.
Now let's define a Monoid for something like Tuple2:
implicit def tupleMonoid[A: Monoid, B: Monoid]: Monoid[(A, B)] = ...
Now you're in a territory where inheritance can't get you anywhere at all. With type classes we can add conditions to type class instances. I.e. a Tuple is a Monoid, when both of its types are also Monoids. With inheritance you can't do this.
I was wondering if scala Either is really a Monad in Category Theory sense?. I know that Monads should have bind and return methods. What is Either's bind then?
Yes, it really is - otherwise it would be in scalaz-outlaws. Either's bind is defined something like:
trait Either[A, B] {
def bind[C](f: B => Either[A, C]) = this match {
case Right(b) => f(b)
case Left(a) => Left(a)
}
}
(in practice it's defined via a typeclass, but the above definition would work)
I guess it's more proper to say that for a fixed A, the type ({type L[B]=Either[A, B]})#L forms a Monad, so Either is more a class of Monads than a Monad in its own right, but that's an exceedingly technical distinction.
But it really is a Monad; it satisfies all the monad laws.
I have this code that I would like to improve on:
sealed abstract class A
case class B() extends A
case class C() extends A
case class D() extends A
case class Foo[+T <: A](a: T)
/** Puts instances that match Foo(B()) in the first list and everything else,
* i.e. Foo(C()) and Foo(D()), in the second list. */
def partition(foos: List[Foo[_ <: A]]): (List[Foo[B]], List[Foo[_ <: A]]) = {
// ...
}
I would like to improve on this in the following respects:
Can I change partition's return type so that it states that there is no Foo[B] in the second list?
Can I get rid of Foo's type parameter T (i.e. change Foo to case class Foo(a: A)) and still declare partition with the same type guarantees? (Obviously, it would have to return something different than (List[Foo], List[Foo]).)
P.S.: Let me know if "shapeless" tag is not relevant for this question.
This question is a little tricky because of the way that Scala mixes up algebraic data types (like your A) and subtyping. In most languages with ADTs, B, C, and D wouldn't be types at all—they'd just be "constructors" (in a sense that's similar to but not the same as OOP constructors).
It wouldn't make sense to talk about a Foo[B] in these languages (like Haskell or OCaml), but in Scala you can, because Scala implements ADTs as case classes (and class objects) extending a base trait or class. That doesn't mean you should go around talking about Foo[B], though, and in general if you want to think in FP terms and use the type system to your advantage, it's a good idea not to.
To answer your specific questions:
No, not really in any convenient way. You could use a tagged union (a list with Either[Foo[C], Foo[D]] elements) or something like Shapeless's Coproduct (a list with Foo[C] :+: Foo[D] :+: CNil elements) to represent "a list of things of type A, but not B", but both approaches are fairly heavy machinery for something that probably isn't the best idea in the first place.
I'd recommend not parametrizing Foo on the subtype of A, but if you want to be able to represent "a Foo that contains a B" at the type level, you're going to need to keep your current approach.
To address your postscript: if you want to generalize over ADTs, Shapeless is definitely applicable—see my blog post here about partitioning by constructor, for example. If you're only doing this for A, though, Shapeless probably won't buy you much.
As a footnote, if I really needed a partitioning operation that split out elements of type Foo[B], I'd probably write it like this:
def partition(foos: List[Foo[A]]): (List[Foo[B]], List[Foo[A]]) =
foos.foldRight((List.empty[Foo[B]], List.empty[Foo[A]])) {
case (Foo(B()), (bs, others)) => (Foo(B()) :: bs, others)
case (other, (bs, others)) => (bs, other :: others)
}
It's not ideal—if we really want a List[Foo[B]], it'd be nice to have a List[Foo[~B]] to represent the leftovers—but it's not too bad.
What I'm about to show is not a very flexible solution. Its usefulness depends entirely on what you're trying to model, but I thought it would be an interesting approach nevertheless.
You could introduce a second trait, say T, in the hierarchy and extend all non-B case classes from it.
sealed trait A
sealed trait T extends A
case class B() extends A
case class C() extends A with T
case class D() extends A with T
case class Foo[+T <: A](a: A)
def partition(foos: List[Foo[A]]): (List[Foo[B]], List[Foo[T]]) = ???
This is code:
object inc extends Poly1 {
implicit val caseInt = at[Int]{_ + 1}
implicit def default[T] = at[T](identity)
}
println(List(3).map(inc))
println(List("3").map(inc))
My question is how poly1 can be blended into map function. TraversableLike defines map signature. Map[B, That](f: A => B), "That" will be provided by CanBuildFrom, so my confusion is about A => B, I look at the source code of Poly1, there are no mapping, how this List(3).map(inc) works ?
This is explained at http://www.chuusai.com/2012/05/10/shapeless-polymorphic-function-values-2/ ; look for the part about polyToMono.
The core idea is that although Poly1 cannot extend scala.Function1, Shapeless provides an implicit conversion so that a polymorphic function can be provided in situations where an ordinary monomorphic function is expected, such as when calling List.map.
There is some extra trickiness needed to make it work both for ordinary types like Int (as in your example) and parameterized types. This is done by wrapping Int as Id[Int] (where Id is the type-level identity function), reducing the un-parameterized case to the parameterized case.
But those blog posts are from 2012 and things are sometimes different in the Shapeless 2.0 that we have today in 2014. When in doubt, consult the Shapeless 2.0 source code.
The 2.0 source doesn't have anything called polyToMono. Where did it go?
As it happens, reify is helpful for investigating these "how the hell does this even compile?" type questions:
scala> reflect.runtime.universe.reify(List(3).map(inc))
res1: reflect.runtime.universe.Expr[List[inc.caseInt.Result]] =
Expr[List[inc.caseInt.Result]](
List.apply(3).map(Poly.inst1($read.inc)(this.inc.caseInt))(
List.canBuildFrom))
So Poly.inst1 seems to be the key here, and yeah, over at https://github.com/milessabin/shapeless/blob/master/core/src/main/scala/shapeless/poly.scala we see:
implicit def inst1[F[_], G[_], T](f : F ~> G) : F[T] => G[T] = f(_)
which is just polyToMono from the blog post, renamed.
Can please someone explain the differences between Functor and Monad in the Scala context?
Scala itself really does not emphasize the Functor and Monad terms that much. I guess using map is the functor side, using flatMap is the Monad side.
For me looking and playing around with scalaz has been so far the best avenue to get a sense of those functional concepts in the scala context (versus the haskell context). Two years ago when I started scala, the scalaz code was gibberish to me, then a few months ago I started looking again and I realized that it's really a clean implementation of that particular style of functional programming.
For instance the Monad implementation shows that a monad is a pointed functor because it extends the Pointed trait (as well as the Applicative trait). I invite you to go look at the code. It has linking in the source itself and it's really easy to follow the links.
So functors are more general. Monads provide additional features. To get a sense of what you can do when you have a functor or when you have a monad, you can look at MA
You'll see utility methods that need an implicit functor (in particular applicative functors) such as sequence and sometime methods that needs a full monad such as replicateM.
Taking scalaz as the reference point, a type F[_] (that is, a type F which is parameterized by some single type) is a functor if a function can be lifted into it. What does this mean:
class Function1W[A, B](self: A => B) {
def lift[F[_]: Functor]: F[A] => F[B]
}
That is, if I have a function A => B, a functor F[_], then I now have a function F[A] => F[B]. This is really just the reverse-way of looking at scala's map method, which (ignoring the CanBuildFrom stuff) is basically:
F[A] => (A => B) => F[B]
If I have a List of Strings, a function from String to Int, then I can obviously produce a List of Ints. This goes for Option, Stream etc. They are all functors
What I find interesting about this is that you might immediately jump to the (incorrect) conclusion that a Functor is a "container" of As. This is an unnecesssary restriction. For example, think about a function X => A. If I have a function X => A and a function A => B then clearly, by composition, I have a function X => B. But now, look at it this way:
type F[Y] = X => Y //F is fixed in X
(X => A) andThen (A => B) is X => B
F[A] A => B F[B]
So the type X => A for some fixed X is also a functor. In scalaz, functor is designed as a trait as follows:
trait Functor[F[_]] { def fmap[A, B](fa: F[A], f: A => B): F[B] }
hence the Function1.lift method above is implemented
def lift[F[_]: Functor]: F[A] => F[B]
= (f: F[A]) => implicitly[Functor[F]].fmap(f, self)
A couple of functor instances:
implicit val OptionFunctor = new Functor[Option] {
def fmap[A, B](fa: Option[A], f: A => B) = fa map f
}
implicit def Functor1Functor[X] = new Functor[({type l[a]=X => a})#l] {
def fmap[A, B](fa: X => B, f: A => B) = f compose fa
}
In scalaz, a monad is designed like this:
trait Monad[M[_]] {
def pure[A](a: A): M[A] //given a value, you can lift it into the monad
def bind[A, B](ma: M[A], f: A => B): M[B]
}
It is not particularly obvious what the usefulness of this might be. It turns out that the answer is "very". I found Daniel Spiewak's Monads are not Metaphors extremely clear in describing why this might be and also Tony Morris's stuff on configuration via the reader monad, a good practical example of what might be meant by writing your program inside a monad.
A while ago I wrote about that: http://gabrielsw.blogspot.com/2011/08/functors-applicative-functors-and.html (I'm no expert though)
The first thing to understand is the type ' T[X] ' : It's a kind of "context" (is useful to encode things in types and with this you're "composing" them) But see the other answers :)
Ok, now you have your types inside a context, say M[A] (A "inside" M), and you have a plain function f:A=>B ... you can't just go ahead and apply it, because the function expects A and you have M[A]. You need some way to "unpack" the content of M, apply the function and "pack" it again. If you have "intimate" knowledge of the internals of M you can do it, if you generalize it in a trait you end with
trait Functor[T[_]]{
def fmap[A,B](f:A=>B)(ta:T[A]):T[B]
}
And that's exactly what a functor is. It transforms a T[A] into a T[B] by applying the function f.
A Monad is a mythical creature with elusive understanding and multiple metaphors, but I found it pretty easy to understand once you get the applicative functor:
Functor allow us to apply functions to things in a context. But what if the functions we want to apply are already in a context? (And is pretty easy to end in that situation if you have functions that take more than one parameter).
Now we need something like a Functor but that also takes functions already in the context and applies them to elements in the context. And that's what the applicative functor is. Here is the signature:
trait Applicative[T[_]] extends Functor[T]{
def pure[A](a:A):T[A]
def <*>[A,B](tf:T[A=>B])(ta:T[A]):T[B]
}
So far so good.
Now comes the monads: what if now you have a function that puts things in the context? It's signature will be g:X=>M[X] ... you can't use a functor because it expects X=>Y so we'll end with M[M[X]], you can't use the applicative functor because is expecting the function already in the context M[X=>Y] .
So we use a monad, that takes a function X=>M[X] and something already in the context M[A] and applies the function to what's inside the context, packing the result in only one context. The signature is:
trait Monad[M[_]] extends Applicative[M]{
def >>=[A,B](ma:M[A])(f:A=>M[B]):M[B]
}
It can be pretty abstract, but if you think on how to work with "Option" it shows you how to compose functions X=>Option[X]
EDIT: Forgot the important thing to tie it: the >>= symbol is called bind and is flatMap in Scala. (Also, as a side note, there are some laws that functors, applicatives, and monads have to follow to work properly).
The best article laying out in details those two notions is "The Essence of the Iterator Pattern " from Eric Torreborre's Blog.
Functor
trait Functor[F[_]] {
def fmap[A, B](f: A => B): F[A] => F[B]
}
One way of interpreting a Functor is to describe it as a computation of values of type A.
For example:
List[A] is a computation returning several values of type A (non-deterministic computation),
Option[A] is for computations that you may or may not have,
Future[A] is a computation of a value of type A that you will get later, and so on.
Another way of picturing it is as some kind of "container" for values of type A.
It is the basic layer from which you define:
PointedFunctor (to create a value of type F[A]) and
Applic (to provide a method applic, being a computed value inside the container F (F[A => B]), to apply to a value F[A]),
Applicative Functor (aggregation of an Applic and a PointedFunctor).
All three elements are used to define a Monad.