I have a construct, let's call it Container. It, as you might guess, is a container for another object, with some headers (a simple map). There are two instances of the container, a success container, or a failed container.
I have a function defined on container, called
flatMap(f: Container[T]=> Container[U]): Container[U]
Pretty familiar right, except unlike a 'real' monad, it's from M[A]->M[B], rather than A->M[B]. This is because I want the mapping functions to have access to all the fields of the container.
Now there's no real problem with this, except it doesn't follow the definitions for a monad and so it doesn't work with for comprehensions as a generator.
Any suggestions, other than changing the flatMap definition, or am I just SoL :)
If you're going from M[A] to M[B] then all you want is map
class Container[A](stuff: A){
def map[B](f: A => B): Container[B] = new Container(f(stuff))
}
The function flatMap really is for functions of type A => M[B] to be able to work on a type of M[A]. Hence,
class Container[A](stuff: A){
def map[B](f: A => B): Container[B] = new Container(f(stuff))
def flatMap[B](f: A => Contains[B]): Container[B] = f(stuff)
}
so you really don't need flatMap in your definition at all.
Related
I'm trying to understand what monads are (not just in scala, but by example using scala). Let's consider the most (in my opinion) simple example of a monad:
scala.Some
As some articles state, every monad in its classic sense should preserve some rules for the flatMap and unit functions.
Here is the definition from scala.Some
#inline final def flatMap[B](f: A => Option[B]): Option[B]
So, understand it better I want to understand it from the category theory standpoint. So, we're considering a monad and it's supposed to be a functor (but between what?).
Here we have to category Option[A] and Option[B] and the flatMap along with the f: A => Option[B] passed into it is supposed to define a Functor between them. But in the tranditional category definition it's a functor from a category to itself.
The category is the category of scala types, where the objects are types and the arrows are functions between values of those types. Option is an endofunctor on this category. For each object (i.e. type) in the Scala category, the Option type constructor maps each type A into a type Option[A].
In addition it maps each arrow f: A => B into an arrow fo: Option[A] => Option[B] which is what Option.map does.
A Monad is a Functor M along with two operations, unit: A => M[A] and join: M[M[A]] => M[A]. For Option, unit(x: A) = Some(x) and join can be defined as:
def join[A](o: Option[Option[A]]): Option[A] = o match {
case None => None
case Some(i) => i
}
flatMap can then be defined as, flatMap(f, m) = join(map(f, m)). Alternatively the monad can be defined using unit and flatMap and join defined as join(m) = flatMap(id, m).
For a coding assignment for school I have to do stuff with flatmap but I have absolutely no idea what it does and I've read a couple pages online and read in my textbook but I still have no true understanding of what it does. I know what map does but for some reason it's hard for me to wrap my head around flatmap. Can anyone help? Thanks.
Just to add some more information- when I look at examples online I DO see how flatmap returns something different from map. But what is flatmap actually doing when its being called on something? How does flatmap actually work? What is it doing before it returns the result?
Here's an analogy.
Imagine you have a big bag filled with shopping vouchers for cartons of eggs. If you have a function which is "use the voucher to buy a carton of eggs" and you called bigBagOfVouchers.map(buyCartonOfEggs), you'd have a bag of cartons of eggs.
However, if you called bigBagOfVouchers.flatMap(buyCartonOfEggs), you'd have a bag of eggs - without any cartons.
flatMap flattens the result by one level. What might have been Bag[Carton[Egg]] is now Bag[Egg].
Functors define map which have type
trait Functor[F[_]] {
def map[A, B](f: A => B)(v: F[A]): F[B]
}
Monads are functors which support two additional operations:
trait Monad[M[_]] extends Functor[M] {
def pure[A](v: A): M[A]
def join[A](m: M[M[A]]): M[A]
}
Join flattens nested values e.g. if m is List then join has type
def joinList[A](l: List[List[A]]): List[A]
If you have a monad m and you map over it, what happens if b is the same monadic type? For example:
def replicate[A](i: Int, value: A): List[A] = ???
val f = new Functor[List] {
def map[A, B](f: A => B)(v: List[A]) = v.map(f)
}
then
f.map(x => replicate(x, x))(List(1,2,3)) == List(List(1), List(2,2), List(3,3,3))
This has type List[List[Int]] while the input is a List[Int]. It's fairly common with a chain of operations to want each step to return the same input type. Since List can also be made into a monad, you can easily create such a list using join:
listMonad.join(List(List(1), List(2,2), List(3,3,3))) == List(1,2,2,3,3,3)
Now you might want to write a function to combine these two operations into one:
trait Monad[M] {
def flatMap[A, B](f: A => M[B])(m: M[A]): M[B] = join(map(f)(m))
}
then you can simply do:
listMonad.flatMap(List(1,2,3), x => replicate(x, x)) == List(1,2,2,3,3,3)
Exactly what flatMap does depends on the monad type constructor M (List in this example) since it depends on map and join.
In reactive programming, you often come into the situation in which you need to use flatMap to convert Future[Future[List]] to Future[List]. For example, you have two functions: get Users from database and process retrieved Users; and both return Future[List[User]]. If you apply map to get and process, the result will be Future[Future[List[User]]] which does not make any sense. Instead, you should use flatMap:
def main(): Future[List[User]] = getUsers flatMap processUsers
def getUsers: Future[List[User]]
def processUsers(users: List[User]): Future[List[User]]
flatMap signature:
/* applies a transformation of the monad "content" by composing
* this monad with an operation resulting in another monad instance
* of the same type
*/
def flatMap(f: A => M[B]): M[B]
is there anyway to understand by its signature (input to output) (except for the name flat) that its flattening the structure? or must I read its implementation to understand that? isn't good coding practice means I can understand by the signature of the function (input to output even without function name) exactly what it does? if so how does flatMap follows this basic programming practice? or does it violates it?
It helps to understand that the type of the thing that flatMap is defined on is also M and would be something like Traversable[A] or a subclass such as a List[A], or another Monad such as Option or Future. Therefore the left hand side of the function definition that flatMap requires (f: A => M[B]) hints to us that this function processes the individual items contained within the Monad, and produces M[B] for each one. The fact that it then returns M[B] rather than M[M[B]] is a hint that some flattening is taking place.
However I disagree that it should be possible to know exactly what a function does by its signature. For example:
Trait Number {
def plus(that: Number): Number
def minus(that: Number): Number
}
Without the function names and possible also some documentation, I don't think it is reasonable to expect that another person can know what plus and minus do.
Does flatMap functional signature (input -> output) proposes its doing any flattening?
Yes, it does.
In fact, join (or flatten), map and unit form a minimal set of primitive functions needed to implement a monad.
flatMap can be implemented in terms of these other functions.
//minimal set
def join[A](mma: M[M[A]]): M[A] = ???
def map[A](ma: M[A], f: A => B): M[B] = ???
def unit[A](a: A): M[A] = ???
def flatMap[A](ma: M[A], f: A => M[B]): M[B] = join(map(ma))
It should now be clear that flatMap flattens the structure of the mapped monad.
For comparison, here's another mimimal set of primitives, where join/flatten is implemented in terms of flatMap.
// minimal set
def unit[A](a: A): M[A] = ???
def flatMap[A](ma: M[A], f: A => M[B]): M[B] = ???
def map[A](ma: M[A], f: A => B): M[B] = flatMap(ma, a => unit(f(a)))
def join[A](mma: M[M[A]]): M[A] = flatMap(mma, ma => ma)
(It seems like I ask too many basic questions, but Scala is very difficult, especially when it comes to the language feature or syntactic sugar, and I come from a Java background..)
I am watching this video: Scalaz State Monad on YouTube. The lecturer wrote these code:
trait State[S, +A] {
def run(initial: S):(S, A)
def map[B](f: A=>B): State[S, B] =
State { s =>
val (s1, a) = run(s)
(s1, f(a))
}
He said the State on the forth line is a "lambda" expression (I may have misheard). I'm a bit confused about this. He did have an object State, which looks like this:
Object State {
def apply[S, A](f: S=>(S, A)): State[S, A] =
new State[S, A] {
def run(i: S) = f(i)
}
}
The lecturer said he was invoking the apply method of Object State by invoking like that, and yes he did pass in a function that returns a correct tuple, but what is that { s=>? Where the hell did he get the s and is this about the implicit mechanism in Scala?
Also the function that is passed in map function changes A to B already, how can it still pass the generics check (from [S, A] to [S, B] assuming A and B are two different types, or are they the same type?If true, why use B not A in map function?)?
The video link is here and is set to be at 18:17
http://youtu.be/Jg3Uv_YWJqI?t=18m17s
Thank you (Monad is a bit daunting to anyone that's not so familiar with functional programming)
You are on right way here.
He passes the function as parameter, but what is the function in general? Function takes argument and return a value. Returned value here is tuple (s1, f(a)), but also we need to reffer to function argument. s in your example is function argument.
It is same as
def map[B](f: A=>B): State[S, B] = {
def buildState(s: S) = {
val (s1, a) = run(s)
(s1, f(a))
}
State(buildState)
}
But, since we dont need this function anywhere else we just inline it in apply call.
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.