So… how off am I in the pictures I was trying to paint below?
Are these worth painting ? I keep struggling to explain monads and their brethren in simpler terms…
Cheers/thanks,
Razie
From: Razvan Cojocaru [mailto:p...@razie.com] Sent: November-12-12 10:02 PM
To: 'Zachary Abbott'; scala-user@googlegroups.com
Subject: RE: [scala-user] Scala and Monads. Why and when to use them over other abstractions.
I will be necessarily somewhat long, somewhat wrong and mostly fuzzy, given my current level of understanding, but I am not one to shy away from making a fool of oneself J If my current understanding is wrong, I can’t wait to be corrected!
Monads (and related concepts from category theory like Functor, Applicative etc) are the next level of abstraction beyond functions…
Functions f : A => B allow you to think and program in a certain way. Once you get used to this “functional programming” you can move on to higher types and higher functions and from there to monads.
For instance, Functors F [A] lift a simple function to something more – the signature tells you their secret
map (f : A => B) : F[A] => F[B]
…they essentially gobble up your function f and return something lazy and higher level – think about that for a second. The laziness aspect of it is not that important at this point.
MAP - you could think of it as taking a simple unix command like “wc -l” and apply it to something “a | wc” where a could be the result of “find *.txt”… I still see it that way after many years…
In scala you use a slightly different version of the same idea List(1,2,3) map (_ + 4).
Why are they useful? Many reasons
For instance – you are normally ‘forbidden’ from using state between two calls to f – you should know that by now. However, INSIDE A FUNCTOR, you could, for the duration of the entire transformation F[A] => F[B]… you could have some state there… this is the beauty of an internalized iterator versus the one you’re used to. That state would be **well encapsulated** there in that transformation, so it could be used.
How that transformation is executed, is up to the specific functor you use. Some can optimize it, some can be dumb while some can use state (like cache a DB connection between calls or whatever).
Let’s have a quick random example: I could have my own functor, working on lists, which keeps the elements sorted. If I apply a random function to it, the result has to be also sorted. You can see the problem? my functor will keep it sorted while an externalized loop may or may not keep it sorted, depending on the programmer.
MySortedList (1,2,3) map (rand(_)) will always be sorted, while List (1,2,3) map (rand(_)) is not…
Without functions and functors, there is no way you could express and enforce that idea – I don’t think…
Monads go even further. Monads have certain laws which give them certain properties which are very useful once you get used to thinking in those terms.
Monads use flatMap rather than map, with a signature
flatMap (f:A=>M[B]) : M[A] => M[B]
as you can see, they also return a transformation, but a higher level one, which include flattening. But because it INCLUDES flattening, it can do it in whichever way it wants.
Why monads are more useful than functors – look at the gobble-able it’s an f : A => M[A] rather than f : A => B – the functors limit you to the shape of the functor, sort of speak – basically if you start with a list of ID’s you will end up with a list of Johns of the same size (or more or less, if the functor is cheating).
Monads are one better, you can start with a list of 5 student ID’s and end up with either 45 grades in a school year or 2 missing registrations… yes, f : A => B has to return exactly one and the same B for an A, while an f : A => M[B] could return for instance empty (called unit) he he…
There’s a lot more to it, as others are trying to convey – try to read as much as you can – there’s no one angle that makes it easy to jump to monad abstractions…
If you are confused by the signatures I used above, it’s ok – no, you don’t have to learn Haskell – there’s an entire series of blog posts to explain the gap J
Cheers,
Razie
From: scala-user@googlegroups.com [mailto:scala-user@googlegroups.com] On Behalf Of Zachary Abbott
Sent: November-06-12 7:12 PM
To: scala-user@googlegroups.com
Subject: [scala-user] Scala and Monads. Why and when to use them over other abstractions.
I think that understanding monads is quite beneficial in Scala, but I'm having trouble finding examples of reasons to use them over some of the abstractions built into scala already.
On Tue, Nov 13, 2012 at 12:08 PM, Razvan Cojocaru <ra...@razie.com> wrote:
> So… how off am I in the pictures I was trying to paint below?
> ** **
> Are these worth painting ? I keep struggling to explain monads and their
> brethren in simpler terms…****
> ** **
> Cheers/thanks,****
> Razie****
> ** **
> *From:* Razvan Cojocaru [mailto:p...@razie.com <p...@razie.com>]
> *Sent:* November-12-12 10:02 PM
> *To:* 'Zachary Abbott'; scala-user@googlegroups.com
> *Subject:* RE: [scala-user] Scala and Monads. Why and when to use them
> over other abstractions.****
> ** **
> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
> given my current level of understanding, but I am not one to shy away from
> making a fool of oneself J If my current understanding is wrong, I can’t
> wait to be corrected!****
> ** **
> Monads (and related concepts from category theory like Functor,
> Applicative etc) are the next level of abstraction beyond functions…****
> ** **
> Functions f : A => B allow you to think and program in a certain way. Once
> you get used to this “functional programming” you can move on to higher
> types and higher functions and from there to monads.****
> ** **
> For instance, Functors F [A] lift a simple function to something more –
> the signature tells you their secret ****
> ** **
> map (f : A => B) : F[A] => F[B]****
> ** **
> …they essentially gobble up your function f and return something lazy and
> higher level – think about that for a second. The laziness aspect of it is
> not that important at this point.****
> ** **
> MAP - you could think of it as taking a simple unix command like “wc -l”
> and apply it to something “a | wc” where a could be the result of “find
> *.txt”… I still see it that way after many years…****
> ** **
> In scala you use a slightly different version of the same idea *List(1,2,3)
> map (_ + 4)*.****
> ** **
> ** **
> Why are they useful? Many reasons****
> ** **
> For instance – you are normally ‘forbidden’ from using state between two
> calls to f – you should know that by now. However, INSIDE A FUNCTOR, you
> could, for the duration of the entire transformation F[A] => F[B]… you
> could have some state there… this is the beauty of an internalized iterator
> versus the one you’re used to. That state would be **well encapsulated**
> there in that transformation, so it could be used.****
> ** **
> How that transformation is executed, is up to the specific functor you
> use. Some can optimize it, some can be dumb while some can use state (like
> cache a DB connection between calls or whatever).****
> ** **
> Let’s have a quick random example: I could have my own functor, working on
> lists, which keeps the elements sorted. If I apply a random function to it,
> the result has to be also sorted. You can see the problem? my functor will
> keep it sorted while an externalized loop may or may not keep it sorted,
> depending on the programmer.****
> ** **
> MySortedList (1,2,3) map (rand(_)) will always be sorted, while
> List (1,2,3) map (rand(_)) is not…****
> ** **
> Without functions and functors, there is no way you could express and
> enforce that idea – I don’t think…****
> ** **
> ** **
> Monads go even further. Monads have certain laws which give them certain
> properties which are very useful once you get used to thinking in those
> terms.****
> ** **
> Monads use flatMap rather than map, with a signature****
> ** **
> flatMap (f:A=>M[B]) : M[A] => M[B] ****
> ** **
> as you can see, they also return a transformation, but a higher level one,
> which include flattening. But because it INCLUDES flattening, it can do it
> in whichever way it wants.****
> ** **
> Why monads are more useful than functors – look at the gobble-able it’s
> an f : A => M[A] rather than f : A => B – the functors limit you to the
> shape of the functor, sort of speak – basically if you start with a list of
> ID’s you will end up with a list of Johns of the same size (or more or
> less, if the functor is cheating).****
> ** **
> Monads are one better, you can start with a list of 5 student ID’s and end
> up with either 45 grades in a school year or 2 missing registrations… yes,
> f : A => B has to return exactly one and the same B for an A, while an f :
> A => M[B] could return for instance empty (called unit) he he…****
> ** **
> There’s a lot more to it, as others are trying to convey – try to read as
> much as you can – there’s no one angle that makes it easy to jump to monad
> abstractions…****
> ** **
> ** **
> If you are confused by the signatures I used above, it’s ok – no, you
> don’t have to learn Haskell – there’s an entire series of blog posts to
> explain the gap J ****
> ** **
> Cheers,****
> Razie****
> ** **
> ** **
> *From:* scala-user@googlegroups.com [mailto:scala-user@googlegroups.com<scala-user@googlegroups.com>]
> *On Behalf Of *Zachary Abbott
> *Sent:* November-06-12 7:12 PM
> *To:* scala-user@googlegroups.com
> *Subject:* [scala-user] Scala and Monads. Why and when to use them over
> other abstractions.****
> ** **
> I think that understanding monads is quite beneficial in Scala, but I'm
> having trouble finding examples of reasons to use them over some of the
> abstractions built into scala already.****
> ** **
> Thank you ****
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
> So� how off am I in the pictures I was trying to paint below?
> Are these worth painting ? I keep struggling to explain monads and
> their brethren in simpler terms�
> Cheers/thanks,
> Razie
> *From:*Razvan Cojocaru [mailto:p...@razie.com]
> *Sent:* November-12-12 10:02 PM
> *To:* 'Zachary Abbott'; scala-user@googlegroups.com
> <mailto:scala-user@googlegroups.com>
> *Subject:* RE: [scala-user] Scala and Monads. Why and when to use them
> over other abstractions.
> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
> given my current level of understanding, but I am not one to shy away
> from making a fool of oneself JIf my current understanding is wrong, I
> can�t wait to be corrected!
> Monads (and related concepts from category theory like Functor,
> Applicative etc) are the next level of abstraction beyond functions�
> Functions f : A => B allow you to think and program in a certain way.
> Once you get used to this �functional programming� you can move on to
> higher types and higher functions and from there to monads.
> For instance, Functors F [A] lift a simple function to something more
> � the signature tells you their secret
> map (f : A => B) : F[A] => F[B]
> �they essentially gobble up your function f and return something lazy
> and higher level � think about that for a second. The laziness aspect
> of it is not that important at this point.
> MAP - you could think of it as taking a simple unix command like �wc
> -l� and apply it to something �a | wc� where a could be the result of
> �find *.txt�� I still see it that way after many years�
> In scala you use a slightly different version of the same idea
> *List(1,2,3) map (_ + 4)*.
> Why are they useful? Many reasons
> For instance � you are normally �forbidden� from using state between
> two calls to f � you should know that by now. However, INSIDE A
> FUNCTOR, you could, for the duration of the entire transformation F[A]
> => F[B]� you could have some state there� this is the beauty of an
> internalized iterator versus the one you�re used to. That state would
> be **well encapsulated** there in that transformation, so it could be
> used.
> How that transformation is executed, is up to the specific functor you
> use. Some can optimize it, some can be dumb while some can use state
> (like cache a DB connection between calls or whatever).
> Let�s have a quick random example: I could have my own functor,
> working on lists, which keeps the elements sorted. If I apply a random
> function to it, the result has to be also sorted. You can see the
> problem? my functor will keep it sorted while an externalized loop may
> or may not keep it sorted, depending on the programmer.
> MySortedList (1,2,3) map (rand(_)) will always be sorted,
> while List (1,2,3) map (rand(_)) is not�
> Without functions and functors, there is no way you could express and
> enforce that idea � I don�t think�
> Monads go even further. Monads have certain laws which give them
> certain properties which are very useful once you get used to thinking
> in those terms.
> Monads use flatMap rather than map, with a signature
> flatMap (f:A=>M[B]) : M[A] => M[B]
> as you can see, they also return a transformation, but a higher level
> one, which include flattening. But because it INCLUDES flattening, it
> can do it in whichever way it wants.
> Why monads are more useful than functors � look at the gobble-able
> it�s an f : A => M[A] rather than f : A => B � the functors limit you
> to the shape of the functor, sort of speak � basically if you start
> with a list of ID�s you will end up with a list of Johns of the same
> size (or more or less, if the functor is cheating).
> Monads are one better, you can start with a list of 5 student ID�s and
> end up with either 45 grades in a school year or 2 missing
> registrations� yes, f : A => B has to return exactly one and the same
> B for an A, while an f : A => M[B] could return for instance empty
> (called unit) he he�
> There�s a lot more to it, as others are trying to convey � try to read
> as much as you can � there�s no one angle that makes it easy to jump
> to monad abstractions�
> If you are confused by the signatures I used above, it�s ok � no, you
> don�t have to learn Haskell � there�s an entire series of blog posts
> to explain the gap J
> Cheers,
> Razie
> *From:*scala-user@googlegroups.com
> <mailto:scala-user@googlegroups.com>
> [mailto:scala-user@googlegroups.com] *On Behalf Of *Zachary Abbott
> *Sent:* November-06-12 7:12 PM
> *To:* scala-user@googlegroups.com <mailto:scala-user@googlegroups.com>
> *Subject:* [scala-user] Scala and Monads. Why and when to use them
> over other abstractions.
> I think that understanding monads is quite beneficial in Scala, but
> I'm having trouble finding examples of reasons to use them over some
> of the abstractions built into scala already.
> Thank you
> -- > You received this message because you are subscribed to the Google
> Groups "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
You mention that Monads use flatmap not map... they also have map because
they are also applicative functors which are Functor's which have map()
Why use use them over the built in abstractions? The pithy answer is
because you can ; -)
But the reason is that every program is a unique specification with its own
abstractions and as such you will undoubtedly have needs that have not been
prepared already for you.
I like the descriptions in "learn you a haskell". Theses higher types are
preserving some context while functions on the values are running. Eg
Option maintains the context if possible failure of a function to provide a
value, and once failed no matter what else you attempt to do to it it stays
failed.
A good question is why would I want my own Monad over and above the common
ones like State or Writer etc?
It is quite easy to think of contexts that are like combinations of the
well known ones eg maintains state and logs what was done, which is a
combination of state and writer. You could build that yourself or look at
monad transformers to create a Frankenstein monad out of the two existing
ones.
You may have a unique context such as testing for compliance to some
constraints as each new bind/flatmap occurs (that may be a combo of state
and Option, say, but may be utterly different).
In any case it is nice to think about the detail of the context you want to
maintain in one place, ie in your monad , than scatter the logic all
through the code everytime some function uses your data structures.
Hope I didn't waffle too much.
Cheers
Karl
On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
> So… how off am I in the pictures I was trying to paint below?
> ** **
> Are these worth painting ? I keep struggling to explain monads and their
> brethren in simpler terms…****
> ** **
> Cheers/thanks,****
> Razie****
> ** **
> *From:* Razvan Cojocaru [mailto:p...@razie.com <p...@razie.com>]
> *Sent:* November-12-12 10:02 PM
> *To:* 'Zachary Abbott'; scala-user@googlegroups.com
> *Subject:* RE: [scala-user] Scala and Monads. Why and when to use them
> over other abstractions.****
> ** **
> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
> given my current level of understanding, but I am not one to shy away from
> making a fool of oneself J If my current understanding is wrong, I can’t
> wait to be corrected!****
> ** **
> Monads (and related concepts from category theory like Functor,
> Applicative etc) are the next level of abstraction beyond functions…****
> ** **
> Functions f : A => B allow you to think and program in a certain way. Once
> you get used to this “functional programming” you can move on to higher
> types and higher functions and from there to monads.****
> ** **
> For instance, Functors F [A] lift a simple function to something more –
> the signature tells you their secret ****
> ** **
> map (f : A => B) : F[A] => F[B]****
> ** **
> …they essentially gobble up your function f and return something lazy and
> higher level – think about that for a second. The laziness aspect of it is
> not that important at this point.****
> ** **
> MAP - you could think of it as taking a simple unix command like “wc -l”
> and apply it to something “a | wc” where a could be the result of “find
> *.txt”… I still see it that way after many years…****
> ** **
> In scala you use a slightly different version of the same idea *List(1,2,3)
> map (_ + 4)*.****
> ** **
> ** **
> Why are they useful? Many reasons****
> ** **
> For instance – you are normally ‘forbidden’ from using state between two
> calls to f – you should know that by now. However, INSIDE A FUNCTOR, you
> could, for the duration of the entire transformation F[A] => F[B]… you
> could have some state there… this is the beauty of an internalized iterator
> versus the one you’re used to. That state would be **well encapsulated**
> there in that transformation, so it could be used.****
> ** **
> How that transformation is executed, is up to the specific functor you
> use. Some can optimize it, some can be dumb while some can use state (like
> cache a DB connection between calls or whatever).****
> ** **
> Let’s have a quick random example: I could have my own functor, working on
> lists, which keeps the elements sorted. If I apply a random function to it,
> the result has to be also sorted. You can see the problem? my functor will
> keep it sorted while an externalized loop may or may not keep it sorted,
> depending on the programmer.****
> ** **
> MySortedList (1,2,3) map (rand(_)) will always be sorted, while
> List (1,2,3) map (rand(_)) is not…****
> ** **
> Without functions and functors, there is no way you could express and
> enforce that idea – I don’t think…****
> ** **
> ** **
> Monads go even further. Monads have certain laws which give them certain
> properties which are very useful once you get used to thinking in those
> terms.****
> ** **
> Monads use flatMap rather than map, with a signature****
> ** **
> flatMap (f:A=>M[B]) : M[A] => M[B] ****
> ** **
> as you can see, they also return a transformation, but a higher level one,
> which include flattening. But because it INCLUDES flattening, it can do it
> in whichever way it wants.****
> ** **
> Why monads are more useful than functors – look at the gobble-able it’s
> an f : A => M[A] rather than f : A => B – the functors limit you to the
> shape of the functor, sort of speak – basically if you start with a list of
> ID’s you will end up with a list of Johns of the same size (or more or
> less, if the functor is cheating).****
> ** **
> Monads are one better, you can start with a list of 5 student ID’s and end
> up with either 45 grades in a school year or 2 missing registrations… yes,
> f : A => B has to return exactly one and the same B for an A, while an f :
> A => M[B] could return for instance empty (called unit) he he…****
> ** **
> There’s a lot more to it, as others are trying to convey – try to read as
> much as you can – there’s no one angle that makes it easy to jump to monad
> abstractions…****
> ** **
> ** **
> If you are confused by the signatures I used above, it’s ok – no, you
> don’t have to learn Haskell – there’s an entire series of blog posts to
> explain the gap J ****
> ** **
> Cheers,****
> Razie****
> ** **
> ** **
> *From:* scala-user@googlegroups.com [mailto:scala-user@googlegroups.com<scala-user@googlegroups.com>]
> *On Behalf Of *Zachary Abbott
> *Sent:* November-06-12 7:12 PM
> *To:* scala-user@googlegroups.com
> *Subject:* [scala-user] Scala and Monads. Why and when to use them over
> other abstractions.****
> ** **
> I think that understanding monads is quite beneficial in Scala, but I'm
> having trouble finding examples of reasons to use them over some of the
> abstractions built into scala already.****
> ** **
> Thank you ****
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
I agree with and understand all that, but it feels too abstract and at the end of the day, my level of understanding was not affected by it. If i were a newbie (of which I am not far) I would probably have not even understood what that meant...
Thanks,
Razvan
On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
> You mention that Monads use flatmap not map... they also have map because they are also applicative functors which are Functor's which have map()
> Why use use them over the built in abstractions? The pithy answer is because you can ; -)
> But the reason is that every program is a unique specification with its own abstractions and as such you will undoubtedly have needs that have not been prepared already for you.
> I like the descriptions in "learn you a haskell". Theses higher types are preserving some context while functions on the values are running. Eg Option maintains the context if possible failure of a function to provide a value, and once failed no matter what else you attempt to do to it it stays failed.
> A good question is why would I want my own Monad over and above the common ones like State or Writer etc?
> It is quite easy to think of contexts that are like combinations of the well known ones eg maintains state and logs what was done, which is a combination of state and writer. You could build that yourself or look at monad transformers to create a Frankenstein monad out of the two existing ones.
> You may have a unique context such as testing for compliance to some constraints as each new bind/flatmap occurs (that may be a combo of state and Option, say, but may be utterly different).
> In any case it is nice to think about the detail of the context you want to maintain in one place, ie in your monad , than scatter the logic all through the code everytime some function uses your data structures.
> Hope I didn't waffle too much.
> Cheers
> Karl
> On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
> So… how off am I in the pictures I was trying to paint below?
> Are these worth painting ? I keep struggling to explain monads and their brethren in simpler terms…
> Cheers/thanks,
> Razie
> From: Razvan Cojocaru [mailto:p...@razie.com] > Sent: November-12-12 10:02 PM
> To: 'Zachary Abbott'; scala-user@googlegroups.com
> Subject: RE: [scala-user] Scala and Monads. Why and when to use them over other abstractions.
> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy, given my current level of understanding, but I am not one to shy away from making a fool of oneself J If my current understanding is wrong, I can’t wait to be corrected!
> Monads (and related concepts from category theory like Functor, Applicative etc) are the next level of abstraction beyond functions…
> Functions f : A => B allow you to think and program in a certain way. Once you get used to this “functional programming” you can move on to higher types and higher functions and from there to monads.
> For instance, Functors F [A] lift a simple function to something more – the signature tells you their secret
> map (f : A => B) : F[A] => F[B]
> …they essentially gobble up your function f and return something lazy and higher level – think about that for a second. The laziness aspect of it is not that important at this point.
> MAP - you could think of it as taking a simple unix command like “wc -l” and apply it to something “a | wc” where a could be the result of “find *.txt”… I still see it that way after many years…
> In scala you use a slightly different version of the same idea List(1,2,3) map (_ + 4).
> Why are they useful? Many reasons
> For instance – you are normally ‘forbidden’ from using state between two calls to f – you should know that by now. However, INSIDE A FUNCTOR, you could, for the duration of the entire transformation F[A] => F[B]… you could have some state there… this is the beauty of an internalized iterator versus the one you’re used to. That state would be **well encapsulated** there in that transformation, so it could be used.
> How that transformation is executed, is up to the specific functor you use. Some can optimize it, some can be dumb while some can use state (like cache a DB connection between calls or whatever).
> Let’s have a quick random example: I could have my own functor, working on lists, which keeps the elements sorted. If I apply a random function to it, the result has to be also sorted. You can see the problem? my functor will keep it sorted while an externalized loop may or may not keep it sorted, depending on the programmer.
> MySortedList (1,2,3) map (rand(_)) will always be sorted, while List (1,2,3) map (rand(_)) is not…
> Without functions and functors, there is no way you could express and enforce that idea – I don’t think…
> Monads go even further. Monads have certain laws which give them certain properties which are very useful once you get used to thinking in those terms.
> Monads use flatMap rather than map, with a signature
> flatMap (f:A=>M[B]) : M[A] => M[B]
> as you can see, they also return a transformation, but a higher level one, which include flattening. But because it INCLUDES flattening, it can do it in whichever way it wants.
> Why monads are more useful than functors – look at the gobble-able it’s an f : A => M[A] rather than f : A => B – the functors limit you to the shape of the functor, sort of speak – basically if you start with a list of ID’s you will end up with a list of Johns of the same size (or more or less, if the functor is cheating).
> Monads are one better, you can start with a list of 5 student ID’s and end up with either 45 grades in a school year or 2 missing registrations… yes, f : A => B has to return exactly one and the same B for an A, while an f : A => M[B] could return for instance empty (called unit) he he…
> There’s a lot more to it, as others are trying to convey – try to read as much as you can – there’s no one angle that makes it easy to jump to monad abstractions…
> If you are confused by the signatures I used above, it’s ok – no, you don’t have to learn Haskell – there’s an entire series of blog posts to explain the gap J
> Cheers,
> Razie
> From: scala-user@googlegroups.com [mailto:scala-user@googlegroups.com] On Behalf Of Zachary Abbott
> Sent: November-06-12 7:12 PM
> To: scala-user@googlegroups.com
> Subject: [scala-user] Scala and Monads. Why and when to use them over other abstractions.
> I think that understanding monads is quite beneficial in Scala, but I'm having trouble finding examples of reasons to use them over some of the abstractions built into scala already.
> Thank you
> -- > You received this message because you are subscribed to the Google Groups "scala-functional" group.
> To unsubscribe from this group, send email to scala-functional+unsubscribe@googlegroups.com.
> -- > You received this message because you are subscribed to the Google Groups "scala-functional" group.
> To unsubscribe from this group, send email to scala-functional+unsubscribe@googlegroups.com.
I find that people understand Functor/map() just fine, but when you jump to
Monad/flatMap() (roughly-speaking) nobody really understands the
consequence of flatMap(). But if you show examples using for-comprehensions
then it is much clearer.
(Using flatMap() directly is usually a bad code smell in "general" code,
IMHO)
I really like Tony's exposition of Monads, using a for-comprehension, where
the comprehension structure *stays the same* while you *vary the monads
used there*, e.g.,
// Example 1: Identity monad
val fm: Identity[Foo]
val bm: Identity[Bar]
for {
foo <- fm
bar <- bm
} yield foo.doStuff(bar)
Now if you change from Identity to Option:
// Example 2: Option monad
val fm: Option[Foo]
val bm: Identity[Bar]
the for-comprehension *doesn't need to change*, but *the semantics have
changed*.
In other words, you can add *effects* (exception handling via
Option/Either, side-effects via IO, etc.) via (monadic) types, rather than
you needing to "rewrite" your sequence into some other kind of structure.
On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
> I agree with and understand all that, but it feels too abstract and at the
> end of the day, my level of understanding was not affected by it. If i were
> a newbie (of which I am not far) I would probably have not even understood
> what that meant...
> Thanks,
> Razvan
> On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
> Hi Razie,
> You mention that Monads use flatmap not map... they also have map because
> they are also applicative functors which are Functor's which have map()
> Why use use them over the built in abstractions? The pithy answer is
> because you can ; -)
> But the reason is that every program is a unique specification with its
> own abstractions and as such you will undoubtedly have needs that have not
> been prepared already for you.
> I like the descriptions in "learn you a haskell". Theses higher types are
> preserving some context while functions on the values are running. Eg
> Option maintains the context if possible failure of a function to provide a
> value, and once failed no matter what else you attempt to do to it it stays
> failed.
> A good question is why would I want my own Monad over and above the
> common ones like State or Writer etc?
> It is quite easy to think of contexts that are like combinations of the
> well known ones eg maintains state and logs what was done, which is a
> combination of state and writer. You could build that yourself or look at
> monad transformers to create a Frankenstein monad out of the two existing
> ones.
> You may have a unique context such as testing for compliance to some
> constraints as each new bind/flatmap occurs (that may be a combo of state
> and Option, say, but may be utterly different).
> In any case it is nice to think about the detail of the context you want
> to maintain in one place, ie in your monad , than scatter the logic all
> through the code everytime some function uses your data structures.
> Hope I didn't waffle too much.
> Cheers
> Karl
> On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
>> So… how off am I in the pictures I was trying to paint below?
>> ** **
>> Are these worth painting ? I keep struggling to explain monads and their
>> brethren in simpler terms…****
>> ** **
>> Cheers/thanks,****
>> Razie****
>> ** **
>> *From:* Razvan Cojocaru [mailto:p...@razie.com <p...@razie.com>]
>> *Sent:* November-12-12 10:02 PM
>> *To:* 'Zachary Abbott'; scala-user@googlegroups.com
>> *Subject:* RE: [scala-user] Scala and Monads. Why and when to use them
>> over other abstractions.****
>> ** **
>> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
>> given my current level of understanding, but I am not one to shy away from
>> making a fool of oneself J If my current understanding is wrong, I can’t
>> wait to be corrected!****
>> ** **
>> Monads (and related concepts from category theory like Functor,
>> Applicative etc) are the next level of abstraction beyond functions…****
>> ** **
>> Functions f : A => B allow you to think and program in a certain way.
>> Once you get used to this “functional programming” you can move on to
>> higher types and higher functions and from there to monads.****
>> ** **
>> For instance, Functors F [A] lift a simple function to something more –
>> the signature tells you their secret ****
>> ** **
>> map (f : A => B) : F[A] => F[B]****
>> ** **
>> …they essentially gobble up your function f and return something lazy and
>> higher level – think about that for a second. The laziness aspect of it is
>> not that important at this point.****
>> ** **
>> MAP - you could think of it as taking a simple unix command like “wc -l”
>> and apply it to something “a | wc” where a could be the result of “find
>> *.txt”… I still see it that way after many years…****
>> ** **
>> In scala you use a slightly different version of the same idea *List(1,2,3)
>> map (_ + 4)*.****
>> ** **
>> ** **
>> Why are they useful? Many reasons****
>> ** **
>> For instance – you are normally ‘forbidden’ from using state between two
>> calls to f – you should know that by now. However, INSIDE A FUNCTOR, you
>> could, for the duration of the entire transformation F[A] => F[B]… you
>> could have some state there… this is the beauty of an internalized iterator
>> versus the one you’re used to. That state would be **well encapsulated**
>> there in that transformation, so it could be used.****
>> ** **
>> How that transformation is executed, is up to the specific functor you
>> use. Some can optimize it, some can be dumb while some can use state (like
>> cache a DB connection between calls or whatever).****
>> ** **
>> Let’s have a quick random example: I could have my own functor, working
>> on lists, which keeps the elements sorted. If I apply a random function to
>> it, the result has to be also sorted. You can see the problem? my functor
>> will keep it sorted while an externalized loop may or may not keep it
>> sorted, depending on the programmer.****
>> ** **
>> MySortedList (1,2,3) map (rand(_)) will always be sorted,
>> while List (1,2,3) map (rand(_)) is not…****
>> ** **
>> Without functions and functors, there is no way you could express and
>> enforce that idea – I don’t think…****
>> ** **
>> ** **
>> Monads go even further. Monads have certain laws which give them certain
>> properties which are very useful once you get used to thinking in those
>> terms.****
>> ** **
>> Monads use flatMap rather than map, with a signature****
>> ** **
>> flatMap (f:A=>M[B]) : M[A] => M[B] ****
>> ** **
>> as you can see, they also return a transformation, but a higher level
>> one, which include flattening. But because it INCLUDES flattening, it can
>> do it in whichever way it wants.****
>> ** **
>> Why monads are more useful than functors – look at the gobble-able it’s
>> an f : A => M[A] rather than f : A => B – the functors limit you to the
>> shape of the functor, sort of speak – basically if you start with a list of
>> ID’s you will end up with a list of Johns of the same size (or more or
>> less, if the functor is cheating).****
>> ** **
>> Monads are one better, you can start with a list of 5 student ID’s and
>> end up with either 45 grades in a school year or 2 missing registrations…
>> yes, f : A => B has to return exactly one and the same B for an A, while an
>> f : A => M[B] could return for instance empty (called unit) he he…****
>> ** **
>> There’s a lot more to it, as others are trying to convey – try to read as
>> much as you can – there’s no one angle that makes it easy to jump to monad
>> abstractions…****
>> ** **
>> ** **
>> If you are confused by the signatures I used above, it’s ok – no, you
>> don’t have to learn Haskell – there’s an entire series of blog posts to
>> explain the gap J ****
>> ** **
>> Cheers,****
>> Razie****
>> ** **
>> ** **
>> *From:* scala-user@googlegroups.com [mailto:scala-user@googlegroups.com<scala-user@googlegroups.com>]
>> *On Behalf Of *Zachary Abbott
>> *Sent:* November-06-12 7:12 PM
>> *To:* scala-user@googlegroups.com
>> *Subject:* [scala-user] Scala and Monads. Why and when to use them over
>> other abstractions.****
>> ** **
>> I think that understanding monads is quite beneficial in Scala, but I'm
>> having trouble finding examples of reasons to use them over some of the
>> abstractions built into scala already.****
>> ** **
>> Thank you ****
>> --
>> You received this message because you are subscribed to the Google Groups
>> "scala-functional" group.
>> To unsubscribe from this group, send email to
>> scala-functional+unsubscribe@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
Interesting - I always thought that you should not be able to change the shape of the monad, I.e. switching from identity to option... While composing them.
I know that scala's for construct allows it as we'll as its collection library, due to the CanBuildFrom but I didn't think that was kosher.
I don't think You're not supposed to be able to escape an I/O monad for instance...
Also, in my practice, I do avoid for and go to map/flatMap directly as a matter of preference. They seem to chain and compose more clearly than a vague for comprehension where everything is in scope...
Thanks,
Razvan
On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:
> I find that people understand Functor/map() just fine, but when you jump to Monad/flatMap() (roughly-speaking) nobody really understands the consequence of flatMap(). But if you show examples using for-comprehensions then it is much clearer.
> (Using flatMap() directly is usually a bad code smell in "general" code, IMHO)
> I really like Tony's exposition of Monads, using a for-comprehension, where the comprehension structure *stays the same* while you *vary the monads used there*, e.g.,
> // Example 1: Identity monad
> val fm: Identity[Foo] > val bm: Identity[Bar]
> for {
> foo <- fm > bar <- bm
> } yield foo.doStuff(bar)
> Now if you change from Identity to Option:
> // Example 2: Option monad
> val fm: Option[Foo] > val bm: Identity[Bar]
> the for-comprehension *doesn't need to change*, but *the semantics have changed*.
> In other words, you can add *effects* (exception handling via Option/Either, side-effects via IO, etc.) via (monadic) types, rather than you needing to "rewrite" your sequence into some other kind of structure.
> .. Adam
> On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
>> I agree with and understand all that, but it feels too abstract and at the end of the day, my level of understanding was not affected by it. If i were a newbie (of which I am not far) I would probably have not even understood what that meant...
>> Thanks,
>> Razvan
>> On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
>>> Hi Razie,
>>> You mention that Monads use flatmap not map... they also have map because they are also applicative functors which are Functor's which have map()
>>> Why use use them over the built in abstractions? The pithy answer is because you can ; -)
>>> But the reason is that every program is a unique specification with its own abstractions and as such you will undoubtedly have needs that have not been prepared already for you.
>>> I like the descriptions in "learn you a haskell". Theses higher types are preserving some context while functions on the values are running. Eg Option maintains the context if possible failure of a function to provide a value, and once failed no matter what else you attempt to do to it it stays failed.
>>> A good question is why would I want my own Monad over and above the common ones like State or Writer etc?
>>> It is quite easy to think of contexts that are like combinations of the well known ones eg maintains state and logs what was done, which is a combination of state and writer. You could build that yourself or look at monad transformers to create a Frankenstein monad out of the two existing ones.
>>> You may have a unique context such as testing for compliance to some constraints as each new bind/flatmap occurs (that may be a combo of state and Option, say, but may be utterly different).
>>> In any case it is nice to think about the detail of the context you want to maintain in one place, ie in your monad , than scatter the logic all through the code everytime some function uses your data structures.
>>> Hope I didn't waffle too much.
>>> Cheers
>>> Karl
>>> On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
>>>> So… how off am I in the pictures I was trying to paint below?
>>>> Are these worth painting ? I keep struggling to explain monads and their brethren in simpler terms…
>>>> Cheers/thanks,
>>>> Razie
>>>> From: Razvan Cojocaru [mailto:p...@razie.com] >>>> Sent: November-12-12 10:02 PM
>>>> To: 'Zachary Abbott'; scala-user@googlegroups.com
>>>> Subject: RE: [scala-user] Scala and Monads. Why and when to use them over other abstractions.
>>>> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy, given my current level of understanding, but I am not one to shy away from making a fool of oneself J If my current understanding is wrong, I can’t wait to be corrected!
>>>> Monads (and related concepts from category theory like Functor, Applicative etc) are the next level of abstraction beyond functions…
>>>> Functions f : A => B allow you to think and program in a certain way. Once you get used to this “functional programming” you can move on to higher types and higher functions and from there to monads.
>>>> For instance, Functors F [A] lift a simple function to something more – the signature tells you their secret
>>>> map (f : A => B) : F[A] => F[B]
>>>> …they essentially gobble up your function f and return something lazy and higher level – think about that for a second. The laziness aspect of it is not that important at this point.
>>>> MAP - you could think of it as taking a simple unix command like “wc -l” and apply it to something “a | wc” where a could be the result of “find *.txt”… I still see it that way after many years…
>>>> In scala you use a slightly different version of the same idea List(1,2,3) map (_ + 4).
>>>> Why are they useful? Many reasons
>>>> For instance – you are normally ‘forbidden’ from using state between two calls to f – you should know that by now. However, INSIDE A FUNCTOR, you could, for the duration of the entire transformation F[A] => F[B]… you could have some state there… this is the beauty of an internalized iterator versus the one you’re used to. That state would be **well encapsulated** there in that transformation, so it could be used.
>>>> How that transformation is executed, is up to the specific functor you use. Some can optimize it, some can be dumb while some can use state (like cache a DB connection between calls or whatever).
>>>> Let’s have a quick random example: I could have my own functor, working on lists, which keeps the elements sorted. If I apply a random function to it, the result has to be also sorted. You can see the problem? my functor will keep it sorted while an externalized loop may or may not keep it sorted, depending on the programmer.
>>>> MySortedList (1,2,3) map (rand(_)) will always be sorted, while List (1,2,3) map (rand(_)) is not…
>>>> Without functions and functors, there is no way you could express and enforce that idea – I don’t think…
>>>> Monads go even further. Monads have certain laws which give them certain properties which are very useful once you get used to thinking in those terms.
>>>> Monads use flatMap rather than map, with a signature
>>>> flatMap (f:A=>M[B]) : M[A] => M[B]
>>>> as you can see, they also return a transformation, but a higher level one, which include flattening. But because it INCLUDES flattening, it can do it in whichever way it wants.
>>>> Why monads are more useful than functors – look at the gobble-able it’s an f : A => M[A] rather than f : A => B – the functors limit you to the shape of the functor, sort of speak – basically if you start with a list of ID’s you will end up with a list of Johns of the same size (or more or less, if the functor is cheating).
>>>> Monads are one better, you can start with a list of 5 student ID’s and end up with either 45 grades in a school year or 2 missing registrations… yes, f : A => B has to return exactly one and the same B for an A, while an f : A => M[B] could return for instance empty (called unit) he he…
>>>> There’s a lot more to it, as others are trying to convey – try to read as much as you can – there’s no one angle that makes it easy to jump to monad abstractions…
>>>> If you are confused by the signatures I used above, it’s ok – no, you don’t have to learn Haskell – there’s an entire series of blog posts to explain the gap J
>>>> Cheers,
>>>> Razie
>>>> From: scala-user@googlegroups.com [mailto:scala-user@googlegroups.com] On Behalf Of Zachary Abbott
>>>> Sent: November-06-12 7:12 PM
>>>> To: scala-user@googlegroups.com
>>>> Subject: [scala-user] Scala and Monads. Why and when to use them over other abstractions.
>>>> I think that understanding monads is quite beneficial in Scala, but I'm having trouble finding examples of reasons to use them over some of the abstractions built into scala already.
>>>> Thank you
>>>> -- >>>> You received this message because you are subscribed to the Google Groups "scala-functional" group.
>>>> To unsubscribe from this group, send email to scala-functional+unsubscribe@googlegroups.com.
>>> -- >>> You received this message because you are subscribed to the Google Groups
> Interesting - I always thought that you should not be able to change the
> shape of the monad, I.e. switching from identity to option... While
> composing them.
> I know that scala's for construct allows it as we'll as its collection
> library, due to the CanBuildFrom but I didn't think that was kosher.
> I don't think You're not supposed to be able to escape an I/O monad for
> instance...
> Also, in my practice, I do avoid for and go to map/flatMap directly as a
> matter of preference. They seem to chain and compose more clearly than a
> vague for comprehension where everything is in scope...
> Thanks,
> Razvan
> On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:
> I find that people understand Functor/map() just fine, but when you jump
> to Monad/flatMap() (roughly-speaking) nobody really understands the
> consequence of flatMap(). But if you show examples using for-comprehensions
> then it is much clearer.
> (Using flatMap() directly is usually a bad code smell in "general" code,
> IMHO)
> I really like Tony's exposition of Monads, using a for-comprehension,
> where the comprehension structure *stays the same* while you *vary the
> monads used there*, e.g.,
> // Example 1: Identity monad
> val fm: Identity[Foo]
> val bm: Identity[Bar]
> for {
> foo <- fm
> bar <- bm
> } yield foo.doStuff(bar)
> Now if you change from Identity to Option:
> // Example 2: Option monad
> val fm: Option[Foo]
> val bm: Identity[Bar]
> the for-comprehension *doesn't need to change*, but *the semantics have
> changed*.
> In other words, you can add *effects* (exception handling via
> Option/Either, side-effects via IO, etc.) via (monadic) types, rather than
> you needing to "rewrite" your sequence into some other kind of structure.
> .. Adam
> On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
>> I agree with and understand all that, but it feels too abstract and at
>> the end of the day, my level of understanding was not affected by it. If i
>> were a newbie (of which I am not far) I would probably have not even
>> understood what that meant...
>> Thanks,
>> Razvan
>> On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
>> Hi Razie,
>> You mention that Monads use flatmap not map... they also have map because
>> they are also applicative functors which are Functor's which have map()
>> Why use use them over the built in abstractions? The pithy answer is
>> because you can ; -)
>> But the reason is that every program is a unique specification with its
>> own abstractions and as such you will undoubtedly have needs that have not
>> been prepared already for you.
>> I like the descriptions in "learn you a haskell". Theses higher types are
>> preserving some context while functions on the values are running. Eg
>> Option maintains the context if possible failure of a function to provide a
>> value, and once failed no matter what else you attempt to do to it it stays
>> failed.
>> A good question is why would I want my own Monad over and above the
>> common ones like State or Writer etc?
>> It is quite easy to think of contexts that are like combinations of the
>> well known ones eg maintains state and logs what was done, which is a
>> combination of state and writer. You could build that yourself or look at
>> monad transformers to create a Frankenstein monad out of the two existing
>> ones.
>> You may have a unique context such as testing for compliance to some
>> constraints as each new bind/flatmap occurs (that may be a combo of state
>> and Option, say, but may be utterly different).
>> In any case it is nice to think about the detail of the context you want
>> to maintain in one place, ie in your monad , than scatter the logic all
>> through the code everytime some function uses your data structures.
>> Hope I didn't waffle too much.
>> Cheers
>> Karl
>> On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
>>> So… how off am I in the pictures I was trying to paint below?
>>> ** **
>>> Are these worth painting ? I keep struggling to explain monads and their
>>> brethren in simpler terms…****
>>> ** **
>>> Cheers/thanks,****
>>> Razie****
>>> ** **
>>> *From:* Razvan Cojocaru [mailto:p...@razie.com <p...@razie.com>]
>>> *Sent:* November-12-12 10:02 PM
>>> *To:* 'Zachary Abbott'; scala-user@googlegroups.com
>>> *Subject:* RE: [scala-user] Scala and Monads. Why and when to use them
>>> over other abstractions.****
>>> ** **
>>> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
>>> given my current level of understanding, but I am not one to shy away from
>>> making a fool of oneself J If my current understanding is wrong, I
>>> can’t wait to be corrected!****
>>> ** **
>>> Monads (and related concepts from category theory like Functor,
>>> Applicative etc) are the next level of abstraction beyond functions…****
>>> ** **
>>> Functions f : A => B allow you to think and program in a certain way.
>>> Once you get used to this “functional programming” you can move on to
>>> higher types and higher functions and from there to monads.****
>>> ** **
>>> For instance, Functors F [A] lift a simple function to something more –
>>> the signature tells you their secret ****
>>> ** **
>>> map (f : A => B) : F[A] => F[B]****
>>> ** **
>>> …they essentially gobble up your function f and return something lazy
>>> and higher level – think about that for a second. The laziness aspect of it
>>> is not that important at this point.****
>>> ** **
>>> MAP - you could think of it as taking a simple unix command like “wc -l”
>>> and apply it to something “a | wc” where a could be the result of “find
>>> *.txt”… I still see it that way after many years…****
>>> ** **
>>> In scala you use a slightly different version of the same idea *List(1,2,3)
>>> map (_ + 4)*.****
>>> ** **
>>> ** **
>>> Why are they useful? Many reasons****
>>> ** **
>>> For instance – you are normally ‘forbidden’ from using state between two
>>> calls to f – you should know that by now. However, INSIDE A FUNCTOR, you
>>> could, for the duration of the entire transformation F[A] => F[B]… you
>>> could have some state there… this is the beauty of an internalized iterator
>>> versus the one you’re used to. That state would be **well encapsulated**
>>> there in that transformation, so it could be used.****
>>> ** **
>>> How that transformation is executed, is up to the specific functor you
>>> use. Some can optimize it, some can be dumb while some can use state (like
>>> cache a DB connection between calls or whatever).****
>>> ** **
>>> Let’s have a quick random example: I could have my own functor, working
>>> on lists, which keeps the elements sorted. If I apply a random function to
>>> it, the result has to be also sorted. You can see the problem? my functor
>>> will keep it sorted while an externalized loop may or may not keep it
>>> sorted, depending on the programmer.****
>>> ** **
>>> MySortedList (1,2,3) map (rand(_)) will always be sorted,
>>> while List (1,2,3) map (rand(_)) is not…****
>>> ** **
>>> Without functions and functors, there is no way you could express and
>>> enforce that idea – I don’t think…****
>>> ** **
>>> ** **
>>> Monads go even further. Monads have certain laws which give them certain
>>> properties which are very useful once you get used to thinking in those
>>> terms.****
>>> ** **
>>> Monads use flatMap rather than map, with a signature****
>>> ** **
>>> flatMap (f:A=>M[B]) : M[A] => M[B] ****
>>> ** **
>>> as you can see, they also return a transformation, but a higher level
>>> one, which include flattening. But because it INCLUDES flattening, it can
>>> do it in whichever way it wants.****
>>> ** **
>>> Why monads are more useful than functors – look at the gobble-able it’s
>>> an f : A => M[A] rather than f : A => B – the functors limit you to the
>>> shape of the functor, sort of speak – basically if you start with a list of
>>> ID’s you will end up with a list of Johns of the same size (or more or
>>> less, if the functor is cheating).****
>>> ** **
>>> Monads are one better, you can start with a list of 5 student ID’s and
>>> end up with either 45 grades in a school year or 2 missing registrations…
>>> yes, f : A => B has to return exactly one and the same B for an A, while an
>>> f : A => M[B] could return for instance empty (called unit) he he…****
>>> ** **
>>> There’s a lot more to it, as others are trying to convey – try to read
>>> as much as you can – there’s no one angle that makes it easy to jump to
>>> monad abstractions…****
>>> ** **
>>> ** **
>>> If you are confused by the signatures I used above, it’s ok – no, you
>>> don’t have to learn Haskell – there’s an entire series of blog posts to
>>> explain the gap J ****
> Interesting - I always thought that you should not be able to change
> the shape of the monad, I.e. switching from identity to option...
> While composing them.
I think that was just a typo in the snippet:
// Example 2: Option monad
val fm: Option[Foo]
val bm: Option[Bar]
What was probably meant is that you can use the same for-comprehension
for M = Identity and M = Option.
Yes, you can use the same for-comprehension, but it is *still* valid if you
only change fm to Option[Foo] and keep vm as Identity[Bar].
The "feature" of monads I'm trying to show is that you *can* switch monads
in order to change the effects you desire, without (necessarily) changing
the sequence of actions, syntax-wise.
On Fri, Nov 16, 2012 at 10:40 AM, Lars Hupel <hu...@in.tum.de> wrote:
> > Interesting - I always thought that you should not be able to change
> > the shape of the monad, I.e. switching from identity to option...
> > While composing them.
> I think that was just a typo in the snippet:
> // Example 2: Option monad
> val fm: Option[Foo]
> val bm: Option[Bar]
> What was probably meant is that you can use the same for-comprehension
> for M = Identity and M = Option.
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
On Fri, Nov 16, 2012 at 10:47 AM, Adam Rosien <a...@rosien.net> wrote:
> Yes, you can use the same for-comprehension, but it is *still* valid if
> you only change fm to Option[Foo] and keep vm as Identity[Bar].
> The "feature" of monads I'm trying to show is that you *can* switch monads
> in order to change the effects you desire, without (necessarily) changing
> the sequence of actions, syntax-wise.
> On Fri, Nov 16, 2012 at 10:40 AM, Lars Hupel <hu...@in.tum.de> wrote:
>> > Interesting - I always thought that you should not be able to change
>> > the shape of the monad, I.e. switching from identity to option...
>> > While composing them.
>> I think that was just a typo in the snippet:
>> // Example 2: Option monad
>> val fm: Option[Foo]
>> val bm: Option[Bar]
>> What was probably meant is that you can use the same for-comprehension
>> for M = Identity and M = Option.
>> --
>> You received this message because you are subscribed to the Google Groups
>> "scala-functional" group.
>> To unsubscribe from this group, send email to
>> scala-functional+unsubscribe@googlegroups.com.
> Yes, you can use the same for-comprehension, but it is *still* valid if you
> only change fm to Option[Foo] and keep vm as Identity[Bar].
Are you sure about that?
scala> val fm: Option[Int] = None
fm: Option[Int] = None
scala> val bm: Identity[String] = Need("foo")
bm: scalaz.Scalaz.Identity[String] = scalaz.Need$$anon$4@1199e863
scala> for { foo <- fm; bar <- bm } yield bm + fm.toString
<console>:16: error: type mismatch;
found : scalaz.Scalaz.Identity[java.lang.String]
required: Option[?]
for { foo <- fm; bar <- bm } yield bm + fm.toString
Apart from that, the misconception that somehow monads allow for
different type constructors in a for-comprehension stems from
`CanBuildFrom` and the collection library.
The fact that you can sometimes mix them in Scala is one of the things I
just find absolutely horrendous. Generically that is completely invalid -
how would you apply join_M: M M a -> M a to (Monad M, Monad N) => (M N a).
On Fri, Nov 16, 2012 at 1:57 PM, Lars Hupel <hu...@in.tum.de> wrote:
> > Yes, you can use the same for-comprehension, but it is *still* valid if
> you
> > only change fm to Option[Foo] and keep vm as Identity[Bar].
> scala> for { foo <- fm; bar <- bm } yield bm + fm.toString
> <console>:16: error: type mismatch;
> found : scalaz.Scalaz.Identity[java.lang.String]
> required: Option[?]
> for { foo <- fm; bar <- bm } yield bm + fm.toString
> Apart from that, the misconception that somehow monads allow for
> different type constructors in a for-comprehension stems from
> `CanBuildFrom` and the collection library.
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
From: scala-functional@googlegroups.com
[mailto:scala-functional@googlegroups.com] On Behalf Of Alec Zorab
Sent: November-16-12 1:38 PM
To: scala-functional@googlegroups.com
Subject: Re: [scala-functional] FW: Scala and Monads. Why and when to use
them over other abstractions.
Obviously a bit artifical, but I'd have a hard time arguing the former was
easier to read. Personally, I prefer this:
import Kleisli._
val e3 = kleisli(a) >==> b >==> c >==> d
but that's mostly for the little fishies
On 16 November 2012 18:14, Razvan Cojocaru <ra...@razie.com> wrote:
Interesting - I always thought that you should not be able to change the
shape of the monad, I.e. switching from identity to option... While
composing them.
I know that scala's for construct allows it as we'll as its collection
library, due to the CanBuildFrom but I didn't think that was kosher.
I don't think You're not supposed to be able to escape an I/O monad for
instance...
Also, in my practice, I do avoid for and go to map/flatMap directly as a
matter of preference. They seem to chain and compose more clearly than a
vague for comprehension where everything is in scope...
Thanks,
Razvan
On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:
I find that people understand Functor/map() just fine, but when you jump to
Monad/flatMap() (roughly-speaking) nobody really understands the consequence
of flatMap(). But if you show examples using for-comprehensions then it is
much clearer.
(Using flatMap() directly is usually a bad code smell in "general" code,
IMHO)
I really like Tony's exposition of Monads, using a for-comprehension, where
the comprehension structure *stays the same* while you *vary the monads used
there*, e.g.,
// Example 1: Identity monad
val fm: Identity[Foo]
val bm: Identity[Bar]
for {
foo <- fm
bar <- bm
} yield foo.doStuff(bar)
Now if you change from Identity to Option:
// Example 2: Option monad
val fm: Option[Foo]
val bm: Identity[Bar]
the for-comprehension *doesn't need to change*, but *the semantics have
changed*.
In other words, you can add *effects* (exception handling via Option/Either,
side-effects via IO, etc.) via (monadic) types, rather than you needing to
"rewrite" your sequence into some other kind of structure.
.. Adam
On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
I agree with and understand all that, but it feels too abstract and at the
end of the day, my level of understanding was not affected by it. If i were
a newbie (of which I am not far) I would probably have not even understood
what that meant...
Thanks,
Razvan
On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
Hi Razie,
You mention that Monads use flatmap not map... they also have map because
they are also applicative functors which are Functor's which have map()
Why use use them over the built in abstractions? The pithy answer is because
you can ; -)
But the reason is that every program is a unique specification with its own
abstractions and as such you will undoubtedly have needs that have not been
prepared already for you.
I like the descriptions in "learn you a haskell". Theses higher types are
preserving some context while functions on the values are running. Eg Option
maintains the context if possible failure of a function to provide a value,
and once failed no matter what else you attempt to do to it it stays failed.
A good question is why would I want my own Monad over and above the common
ones like State or Writer etc?
It is quite easy to think of contexts that are like combinations of the well
known ones eg maintains state and logs what was done, which is a combination
of state and writer. You could build that yourself or look at monad
transformers to create a Frankenstein monad out of the two existing ones.
You may have a unique context such as testing for compliance to some
constraints as each new bind/flatmap occurs (that may be a combo of state
and Option, say, but may be utterly different).
In any case it is nice to think about the detail of the context you want to
maintain in one place, ie in your monad , than scatter the logic all through
the code everytime some function uses your data structures.
Hope I didn't waffle too much.
Cheers
Karl
On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
So. how off am I in the pictures I was trying to paint below?
Are these worth painting ? I keep struggling to explain monads and their
brethren in simpler terms.
Cheers/thanks,
Razie
From: Razvan Cojocaru [mailto:p...@razie.com] Sent: November-12-12 10:02 PM
To: 'Zachary Abbott'; scala-user@googlegroups.com
Subject: RE: [scala-user] Scala and Monads. Why and when to use them over
other abstractions.
I will be necessarily somewhat long, somewhat wrong and mostly fuzzy, given
my current level of understanding, but I am not one to shy away from making
a fool of oneself J If my current understanding is wrong, I can't wait to be
corrected!
Monads (and related concepts from category theory like Functor, Applicative
etc) are the next level of abstraction beyond functions.
Functions f : A => B allow you to think and program in a certain way. Once
you get used to this "functional programming" you can move on to higher
types and higher functions and from there to monads.
For instance, Functors F [A] lift a simple function to something more - the
signature tells you their secret
map (f : A => B) : F[A] => F[B]
.they essentially gobble up your function f and return something lazy and
higher level - think about that for a second. The laziness aspect of it is
not that important at this point.
MAP - you could think of it as taking a simple unix command like "wc -l" and
apply it to something "a | wc" where a could be the result of "find *.txt".
I still see it that way after many years.
In scala you use a slightly different version of the same idea List(1,2,3)
map (_ + 4).
Why are they useful? Many reasons
For instance - you are normally 'forbidden' from using state between two
calls to f - you should know that by now. However, INSIDE A FUNCTOR, you
could, for the duration of the entire transformation F[A] => F[B]. you could
have some state there. this is the beauty of an internalized iterator versus
the one you're used to. That state would be **well encapsulated** there in
that transformation, so it could be used.
How that transformation is executed, is up to the specific functor you use.
Some can optimize it, some can be dumb while some can use state (like cache
a DB connection between calls or whatever).
Let's have a quick random example: I could have my own functor, working on
lists, which keeps the elements sorted. If I apply a random function to it,
the result has to be also sorted. You can see the problem? my functor will
keep it sorted while an externalized loop may or may not keep it sorted,
depending on the programmer.
MySortedList (1,2,3) map (rand(_)) will always be sorted, while
List (1,2,3) map (rand(_)) is not.
Without functions and functors, there is no way you could express and
enforce that idea - I don't think.
Monads go even further. Monads have certain laws which give them certain
properties which are very useful once you get used to thinking in those
terms.
Monads use flatMap rather than map, with a signature
flatMap (f:A=>M[B]) : M[A] => M[B]
as you can see, they also return a transformation, but a higher level one,
which include flattening. But because it INCLUDES flattening, it can do it
in whichever way it wants.
Why monads are more useful than functors - look at the gobble-able it's an
f : A => M[A] rather than f : A => B - the functors limit you to the shape
of the functor, sort of speak - basically if you start with a list of ID's
you will end up with a list of Johns of the same size (or more or less, if
the functor is cheating).
Monads are one better, you can start with a list of 5 student ID's and end
up with either 45 grades in a school year or 2 missing registrations. yes, f
: A => B has to return exactly one and the same B for an A, while an f : A
=> M[B] could return for instance empty (called unit) he he.
There's a lot more to it, as others are trying to convey - try to read as
much as you can - there's no one angle that makes it easy to jump to monad
abstractions.
If you are confused by the signatures I used above, it's ok - no, you don't
have to learn Haskell - there's an entire series of blog posts to explain
the gap J
Cheers,
Razie
From: scala-user@googlegroups.com [mailto:scala-user@googlegroups.com] On
Behalf Of Zachary Abbott
Sent:
...
> *From:* scala-functional@googlegroups.com [mailto:
> scala-functional@googlegroups.com] *On Behalf Of *Alec Zorab
> *Sent:* November-16-12 1:38 PM
> *To:* scala-functional@googlegroups.com
> *Subject:* Re: [scala-functional] FW: Scala and Monads. Why and when to
> use them over other abstractions.****
> Obviously a bit artifical, but I'd have a hard time arguing the former was
> easier to read. Personally, I prefer this: ****
> ** **
> import Kleisli._****
> val e3 = kleisli(a) >==> b >==> c >==> d****
> ** **
> but that's mostly for the little fishies****
> ** **
> On 16 November 2012 18:14, Razvan Cojocaru <ra...@razie.com> wrote:****
> Interesting - I always thought that you should not be able to change the
> shape of the monad, I.e. switching from identity to option... While
> composing them. ****
> ** **
> I know that scala's for construct allows it as we'll as its collection
> library, due to the CanBuildFrom but I didn't think that was kosher. ****
> ** **
> I don't think You're not supposed to be able to escape an I/O monad for
> instance...****
> ** **
> Also, in my practice, I do avoid for and go to map/flatMap directly as a
> matter of preference. They seem to chain and compose more clearly than a
> vague for comprehension where everything is in scope... ****
> Thanks,****
> Razvan****
> On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:****
> I find that people understand Functor/map() just fine, but when you jump
> to Monad/flatMap() (roughly-speaking) nobody really understands the
> consequence of flatMap(). But if you show examples using for-comprehensions
> then it is much clearer. ****
> ** **
> (Using flatMap() directly is usually a bad code smell in "general" code,
> IMHO)****
> ** **
> I really like Tony's exposition of Monads, using a for-comprehension,
> where the comprehension structure *stays the same* while you *vary the
> monads used there*, e.g.,****
> ** **
> // Example 1: Identity monad****
> val fm: Identity[Foo] ****
> val bm: Identity[Bar]****
> ** **
> for {****
> foo <- fm ****
> bar <- bm****
> } yield foo.doStuff(bar)****
> ** **
> Now if you change from Identity to Option:****
> ** **
> // Example 2: Option monad****
> val fm: Option[Foo] ****
> val bm: Identity[Bar]****
> ** **
> the for-comprehension *doesn't need to change*, but *the semantics have
> changed*. ****
> ** **
> In other words, you can add *effects* (exception handling via
> Option/Either, side-effects via IO, etc.) via (monadic) types, rather than
> you needing to "rewrite" your sequence into some other kind of structure.*
> ***
> ** **
> .. Adam****
> ** **
> ** **
> On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:*
> ***
> I agree with and understand all that, but it feels too abstract and at the
> end of the day, my level of understanding was not affected by it. If i were
> a newbie (of which I am not far) I would probably have not even understood
> what that meant...
> Thanks,****
> Razvan****
> On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:*
> ***
> Hi Razie,****
> You mention that Monads use flatmap not map... they also have map because
> they are also applicative functors which are Functor's which have map()***
> *
> Why use use them over the built in abstractions? The pithy answer is
> because you can ; -)
> But the reason is that every program is a unique specification with its
> own abstractions and as such you will undoubtedly have needs that have not
> been prepared already for you.****
> I like the descriptions in "learn you a haskell". Theses higher types are
> preserving some context while functions on the values are running. Eg
> Option maintains the context if possible failure of a function to provide a
> value, and once failed no matter what else you attempt to do to it it stays
> failed.****
> A good question is why would I want my own Monad over and above the
> common ones like State or Writer etc?****
> It is quite easy to think of contexts that are like combinations of the
> well known ones eg maintains state and logs what was done, which is a
> combination of state and writer. You could build that yourself or look at
> monad transformers to create a Frankenstein monad out of the two existing
> ones.****
> You may have a unique context such as testing for compliance to some
> constraints as each new bind/flatmap occurs (that may be a combo of state
> and Option, say, but may be utterly different).****
> In any case it is nice to think about the detail of the context you want
> to maintain in one place, ie in your monad , than scatter the logic all
> through the code everytime some function uses your data structures.****
> Hope I didn't waffle too much.****
> Cheers****
> Karl****
> On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:****
> So… how off am I in the pictures I was trying to paint below?****
> ****
> Are these worth painting ? I keep struggling to explain monads and their
> brethren in simpler terms…****
> ****
> Cheers/thanks,****
> Razie****
> ****
> *From:* Razvan Cojocaru [mailto:p...@razie.com <p...@razie.com>]
> *Sent:* November-12-12 10:02 PM
> *To:* 'Zachary Abbott'; scala-user@googlegroups.com
> *Subject:* RE: [scala-user] Scala and Monads. Why and when to use them
> over other abstractions.****
> ****
> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
> given my current level of understanding, but I am not one to shy away from
> making a fool of oneself J If my current understanding is wrong, I can’t
> wait to be corrected!****
> ****
> Monads (and related concepts from category theory like Functor,
> Applicative etc) are the next level of abstraction beyond functions…****
> ****
> Functions f : A => B allow you to think and program in a certain way. Once
> you get used to this “functional programming” you can move on to higher
> types and higher functions and from there to monads.****
> ****
> For instance, Functors F [A] lift a simple function to something more –
> the signature tells you their secret ****
> ****
> map (f : A => B) : F[A] => F[B]****
> ****
> …they essentially gobble up your function f and return something lazy and
> higher level – think about that for a second. The laziness aspect of it is
> not that important at this point.****
> ****
> MAP - you could think of it as taking a simple unix command like “wc -l”
> and apply it to something “a | wc” where a could be the result of “find
> *.txt”… I still see it that way after many years…****
> ****
> In scala you use a slightly different version of the same idea *List(1,2,3)
> map (_ + 4)*.****
> ****
> ****
> Why are they useful? Many reasons****
> ****
> For instance – you are normally ‘forbidden’ from using state between two
> calls to f – you should know that by now. However, INSIDE A FUNCTOR, you
> could, for the duration of the entire transformation F[A] => F[B]… you
> could have some state there… this is the beauty of an internalized iterator
> versus the one you’re used to. That state would be **well encapsulated**
> there in that transformation, so it could be used.****
> ****
> How that transformation is executed, is up to the specific functor you
> use. Some can optimize it, some can be dumb while some can use state (like
> cache a DB connection between calls or whatever).****
> ****
> Let’s have a quick random example: I could have my own functor, working on
> lists, which keeps the elements sorted. If I apply a random function to it,
> the result has to be also sorted. You can see the problem? my functor will
> keep it sorted while an externalized loop may or may not keep it sorted,
> depending on the programmer.****
> ****
> MySortedList (1,2,3) map (rand(_)) will always be sorted, while
> List (1,2,3) map (rand(_)) is not…****
> ****
> Without functions and functors, there is no way you could express and
> enforce that idea – I don’t think…****
> ****
> ****
> Monads go even further. Monads have certain laws which give them certain
> properties which are very useful once you get used to thinking in those
> terms.****
> ****
> Monads use flatMap rather than map, with a signature****
Yeah good point. Sorry about adding confusion with a bad code snippet.
I guess the "keep the for-comprehension, vary the monad" idea is most
appropriate in a teaching setting, where it emphasizes effects-as-types,
which most beginners haven't internalized yet, and would attempt to code
the effects with complex logic.
On Fri, Nov 16, 2012 at 10:57 AM, Lars Hupel <hu...@in.tum.de> wrote:
> > Yes, you can use the same for-comprehension, but it is *still* valid if
> you
> > only change fm to Option[Foo] and keep vm as Identity[Bar].
> scala> for { foo <- fm; bar <- bm } yield bm + fm.toString
> <console>:16: error: type mismatch;
> found : scalaz.Scalaz.Identity[java.lang.String]
> required: Option[?]
> for { foo <- fm; bar <- bm } yield bm + fm.toString
> Apart from that, the misconception that somehow monads allow for
> different type constructors in a for-comprehension stems from
> `CanBuildFrom` and the collection library.
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
Then I use the for J but in nice clean compostable code, it shouldn't - at
least that's what I try for.
Compostable - that autocorrect was so funny I left it in place J J I
obviously meant compose-able but English language is not monadic yet J
Cheers
From: scala-functional@googlegroups.com
[mailto:scala-functional@googlegroups.com] On Behalf Of Alec Zorab
Sent: November-16-12 2:51 PM
To: scala-functional@googlegroups.com
Subject: RE: [scala-functional] FW: Scala and Monads. Why and when to use
them over other abstractions.
What do you do when d() takes an a? What
On Nov 16, 2012 7:38 PM, "Razvan Cojocaru" <ra...@razie.com> wrote:
Almost - quite seriously yes, I prefer this:
Val e1 = a(t) flatMap b flatMap c flatMap d
Especially if you use some nice symbols, I think you can import them from
scalaz:
Val e1 = a(t) >>= b >>= c >>= d
your first version, it is rather equivalent to my first, except for scope
and complication
see this:
import scalaz._
import Scalaz._
List(1,2,3) flatMap (0 until _+10) flatMap (0 until _-10)
From: scala-functional@googlegroups.com
[mailto:scala-functional@googlegroups.com] On Behalf Of Alec Zorab
Sent: November-16-12 1:38 PM
To: scala-functional@googlegroups.com
Subject: Re: [scala-functional] FW: Scala and Monads. Why and when to use
them over other abstractions.
Obviously a bit artifical, but I'd have a hard time arguing the former was
easier to read. Personally, I prefer this:
import Kleisli._
val e3 = kleisli(a) >==> b >==> c >==> d
but that's mostly for the little fishies
On 16 November 2012 18:14, Razvan Cojocaru <ra...@razie.com> wrote:
Interesting - I always thought that you should not be able to change the
shape of the monad, I.e. switching from identity to option... While
composing them.
I know that scala's for construct allows it as we'll as its collection
library, due to the CanBuildFrom but I didn't think that was kosher.
I don't think You're not supposed to be able to escape an I/O monad for
instance...
Also, in my practice, I do avoid for and go to map/flatMap directly as a
matter of preference. They seem to chain and compose more clearly than a
vague for comprehension where everything is in scope...
Thanks,
Razvan
On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:
I find that people understand Functor/map() just fine, but when you jump to
Monad/flatMap() (roughly-speaking) nobody really understands the consequence
of flatMap(). But if you show examples using for-comprehensions then it is
much clearer.
(Using flatMap() directly is usually a bad code smell in "general" code,
IMHO)
I really like Tony's exposition of Monads, using a for-comprehension, where
the comprehension structure *stays the same* while you *vary the monads used
there*, e.g.,
// Example 1: Identity monad
val fm: Identity[Foo]
val bm: Identity[Bar]
for {
foo <- fm
bar <- bm
} yield foo.doStuff(bar)
Now if you change from Identity to Option:
// Example 2: Option monad
val fm: Option[Foo]
val bm: Identity[Bar]
the for-comprehension *doesn't need to change*, but *the semantics have
changed*.
In other words, you can add *effects* (exception handling via Option/Either,
side-effects via IO, etc.) via (monadic) types, rather than you needing to
"rewrite" your sequence into some other kind of structure.
.. Adam
On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
I agree with and understand all that, but it feels too abstract and at the
end of the day, my level of understanding was not affected by it. If i were
a newbie (of which I am not far) I would probably have not even understood
what that meant...
Thanks,
Razvan
On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
Hi Razie,
You mention that Monads use flatmap not map... they also have map because
they are also applicative functors which are Functor's which have map()
Why use use them over the built in abstractions? The pithy answer is because
you can ; -)
But the reason is that every program is a unique specification with its own
abstractions and as such you will undoubtedly have needs that have not been
prepared already for you.
I like the descriptions in "learn you a haskell". Theses higher types are
preserving some context while functions on the values are running. Eg Option
maintains the context if possible failure of a function to provide a value,
and once failed no matter what else you attempt to do to it it stays failed.
A good question is why would I want my own Monad over and above the common
ones like State or Writer etc?
It is quite easy to think of contexts that are like combinations of the well
known ones eg maintains state and logs what was done, which is a combination
of state and writer. You could build that yourself or look at monad
transformers to create a Frankenstein monad out of the two existing ones.
You may have a unique context such as testing for compliance to some
constraints as each new bind/flatmap occurs (that may be a combo of state
and Option, say, but may be utterly different).
In any case it is nice to think about the detail of the context you want to
maintain in one place, ie in your monad , than scatter the logic all through
the code everytime some function uses your data structures.
Hope I didn't waffle too much.
Cheers
Karl
On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
So. how off am I in the pictures I was trying to paint below?
Are these worth painting ? I keep struggling to explain monads and their
brethren in simpler terms.
Cheers/thanks,
Razie
From: Razvan Cojocaru [mailto:p...@razie.com] Sent: November-12-12 10:02 PM
To: 'Zachary Abbott'; scala-user@googlegroups.com
Subject: RE: [scala-user] Scala and Monads. Why and when to use them over
other abstractions.
I will be necessarily somewhat long, somewhat wrong and mostly fuzzy, given
my current level of understanding, but I am not one to shy away from making
a fool of oneself J If my current understanding is wrong, I can't wait to be
corrected!
Monads (and related concepts from category theory like Functor, Applicative
etc) are the next level of abstraction beyond functions.
Functions f : A => B allow you to think and program in a certain way. Once
you get used to this "functional programming" you can move on to higher
types and higher functions and from there to monads.
For instance, Functors F [A] lift a simple function to something more - the
signature tells you their secret
map (f : A => B) : F[A] => F[B]
.they essentially gobble up your function f and return something lazy and
higher level - think about that for a second. The laziness aspect of it is
not that important at this point.
MAP - you could think of it as taking a simple unix command like "wc -l" and
apply it to something "a | wc" where a could be the result of "find *.txt".
I still see it that way after many years.
In scala you use a slightly different version of the same idea List(1,2,3)
map (_ + 4).
Why are they useful? Many reasons
For instance - you are normally 'forbidden' from using state between two
calls to f - you should know that by now. However, INSIDE A FUNCTOR, you
could, for the duration of the entire transformation F[A] => F[B]. you could
have some state there. this is the beauty of an internalized iterator versus
the one you're used to. That state would be **well encapsulated** there in
that transformation, so it could be used.
How that transformation is executed, is up to the specific functor you use.
Some can optimize it, some can be dumb while some can use state (like cache
a DB connection between calls or whatever).
Let's have a quick random example: I could have my own functor, working on
lists, which keeps the elements sorted. If I apply a random function to it,
the result has to be also sorted. You can see the problem? my functor will
keep it sorted while an externalized loop may or may not keep it sorted,
depending on the programmer.
MySortedList (1,2,3) map (rand(_)) will always be sorted, while
List (1,2,3) map (rand(_)) is not.
Without functions and functors, there is no way you could express and
enforce that idea - I don't think.
Monads go even further. Monads have certain laws which give them certain
properties which are very useful once you get used to thinking in those
terms.
Monads use flatMap rather than map, with a signature
flatMap (f:A=>M[B]) : M[A] => M[B]
as you can see, they also return a transformation, but a higher level one,
which include flattening. But because it INCLUDES flattening, it can do it
in whichever way it wants.
Why monads are more useful than functors - look at the gobble-able it's an
f : A => M[A] rather than f : A => B - the functors limit you to the shape
of the functor, sort of speak - basically if you start with a list of ID's
you will end up with a list of Johns of the same size (or more or less, if
the functor is cheating).
Monads are one better, you can start with a list of 5 student ID's and end
up with either 45 grades
...
Don't get me wrong - I do use the for, but I try not to. here's an example
where it's perfectly suitable (my screwy code - this is a nice one, I have
much worse )
(for (
// play 2.0 workaround - remove in play 2.1
date <- (try { Option(DateTime.parse(expiry.dec)) } catch { case _ =>
(try { Option(DateTime.parse(expiry.replaceAll(" ", "+").dec)) } catch {
case _ => None }) }) orErr ("token faked or expired");
notExpired <- date.isAfterNow orCorr cExpired;
au <- Users.findUserById(userId);
admin <- auth orCorr cNoAuth;
modUname <- moderator(WID("Club", club));
isMod <- (admin.hasPerm(Perm.adminDb) || admin.userName == modUname)
orErr ("You do not have permission!!!");
isA <- checkActive(au);
ok <- hows.contains(how) orErr ("invalid role")
) yield {
.
}) getOrElse {
.
}
From: Razvan Cojocaru [mailto:ra...@razie.com] Sent: November-16-12 2:54 PM
To: scala-functional@googlegroups.com
Subject: RE: [scala-functional] FW: Scala and Monads. Why and when to use
them over other abstractions.
Then I use the for J but in nice clean compostable code, it shouldn't - at
least that's what I try for.
Compostable - that autocorrect was so funny I left it in place J J I
obviously meant compose-able but English language is not monadic yet J
Cheers
From: scala-functional@googlegroups.com
[mailto:scala-functional@googlegroups.com] On Behalf Of Alec Zorab
Sent: November-16-12 2:51 PM
To: scala-functional@googlegroups.com
Subject: RE: [scala-functional] FW: Scala and Monads. Why and when to use
them over other abstractions.
What do you do when d() takes an a? What
On Nov 16, 2012 7:38 PM, "Razvan Cojocaru" <ra...@razie.com> wrote:
Almost - quite seriously yes, I prefer this:
Val e1 = a(t) flatMap b flatMap c flatMap d
Especially if you use some nice symbols, I think you can import them from
scalaz:
Val e1 = a(t) >>= b >>= c >>= d
your first version, it is rather equivalent to my first, except for scope
and complication
see this:
import scalaz._
import Scalaz._
List(1,2,3) flatMap (0 until _+10) flatMap (0 until _-10)
From: scala-functional@googlegroups.com
[mailto:scala-functional@googlegroups.com] On Behalf Of Alec Zorab
Sent: November-16-12 1:38 PM
To: scala-functional@googlegroups.com
Subject: Re: [scala-functional] FW: Scala and Monads. Why and when to use
them over other abstractions.
Obviously a bit artifical, but I'd have a hard time arguing the former was
easier to read. Personally, I prefer this:
import Kleisli._
val e3 = kleisli(a) >==> b >==> c >==> d
but that's mostly for the little fishies
On 16 November 2012 18:14, Razvan Cojocaru <ra...@razie.com> wrote:
Interesting - I always thought that you should not be able to change the
shape of the monad, I.e. switching from identity to option... While
composing them.
I know that scala's for construct allows it as we'll as its collection
library, due to the CanBuildFrom but I didn't think that was kosher.
I don't think You're not supposed to be able to escape an I/O monad for
instance...
Also, in my practice, I do avoid for and go to map/flatMap directly as a
matter of preference. They seem to chain and compose more clearly than a
vague for comprehension where everything is in scope...
Thanks,
Razvan
On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:
I find that people understand Functor/map() just fine, but when you jump to
Monad/flatMap() (roughly-speaking) nobody really understands the consequence
of flatMap(). But if you show examples using for-comprehensions then it is
much clearer.
(Using flatMap() directly is usually a bad code smell in "general" code,
IMHO)
I really like Tony's exposition of Monads, using a for-comprehension, where
the comprehension structure *stays the same* while you *vary the monads used
there*, e.g.,
// Example 1: Identity monad
val fm: Identity[Foo]
val bm: Identity[Bar]
for {
foo <- fm
bar <- bm
} yield foo.doStuff(bar)
Now if you change from Identity to Option:
// Example 2: Option monad
val fm: Option[Foo]
val bm: Identity[Bar]
the for-comprehension *doesn't need to change*, but *the semantics have
changed*.
In other words, you can add *effects* (exception handling via Option/Either,
side-effects via IO, etc.) via (monadic) types, rather than you needing to
"rewrite" your sequence into some other kind of structure.
.. Adam
On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
I agree with and understand all that, but it feels too abstract and at the
end of the day, my level of understanding was not affected by it. If i were
a newbie (of which I am not far) I would probably have not even understood
what that meant...
Thanks,
Razvan
On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
Hi Razie,
You mention that Monads use flatmap not map... they also have map because
they are also applicative functors which are Functor's which have map()
Why use use them over the built in abstractions? The pithy answer is because
you can ; -)
But the reason is that every program is a unique specification with its own
abstractions and as such you will undoubtedly have needs that have not been
prepared already for you.
I like the descriptions in "learn you a haskell". Theses higher types are
preserving some context while functions on the values are running. Eg Option
maintains the context if possible failure of a function to provide a value,
and once failed no matter what else you attempt to do to it it stays failed.
A good question is why would I want my own Monad over and above the common
ones like State or Writer etc?
It is quite easy to think of contexts that are like combinations of the well
known ones eg maintains state and logs what was done, which is a combination
of state and writer. You could build that yourself or look at monad
transformers to create a Frankenstein monad out of the two existing ones.
You may have a unique context such as testing for compliance to some
constraints as each new bind/flatmap occurs (that may be a combo of state
and Option, say, but may be utterly different).
In any case it is nice to think about the detail of the context you want to
maintain in one place, ie in your monad , than scatter the logic all through
the code everytime some function uses your data structures.
Hope I didn't waffle too much.
Cheers
Karl
On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
So. how off am I in the pictures I was trying to paint below?
Are these worth painting ? I keep struggling to explain monads and their
brethren in simpler terms.
Cheers/thanks,
Razie
From: Razvan Cojocaru [mailto:p...@razie.com] Sent: November-12-12 10:02 PM
To: 'Zachary Abbott'; scala-user@googlegroups.com
Subject: RE: [scala-user] Scala and Monads. Why and when to use them over
other abstractions.
I will be necessarily somewhat long, somewhat wrong and mostly fuzzy, given
my current level of understanding, but I am not one to shy away from making
a fool of oneself J If my current understanding is wrong, I can't wait to be
corrected!
Monads (and related concepts from category theory like Functor, Applicative
etc) are the next level of abstraction beyond functions.
Functions f : A => B allow you to think and program in a certain way. Once
you get used to this "functional programming" you can move on to higher
types and higher functions and from there to monads.
For instance, Functors F [A] lift a simple function to something more - the
signature tells you their secret
map (f : A => B) : F[A] => F[B]
.they essentially gobble up your function f and return something lazy and
higher level - think about that for a second. The laziness aspect of it is
not that important at this point.
MAP - you could think of it as taking a simple unix command like "wc -l" and
apply it to something "a | wc" where a could be the result of "find *.txt".
I still see it that way after many years.
In scala you use a slightly different version of the same idea List(1,2,3)
map (_ + 4).
Why are they useful? Many reasons
For instance - you are normally 'forbidden' from using state between two
calls to f - you should know that by now. However, INSIDE A FUNCTOR, you
could, for the duration of the entire transformation F[A] => F[B]. you could
have some state there. this is the beauty of an internalized iterator versus
the one you're used to. That state would be **well encapsulated** there in
that transformation, so it could be used.
How that transformation is executed, is up to the specific functor you use.
Some can optimize it, some can be dumb while some can use state (like cache
a DB connection between calls or whatever).
Let's have a quick random example: I could have my own functor, working on
lists, which keeps the elements sorted. If I apply a random function to it,
the result has to be also sorted. You can see the problem? my functor will
keep it sorted while an externalized loop may or may not keep it sorted,
depending on the programmer.
...
I wish to reiterate this. Scala does allow mixing of type constructors in a
comprehension. This is, to reuse the description due to its high accuracy,
horrendous. You might hear claims of increased flexibility. Nothing could
be further from the truth. It's snake oil.
For the purposes of learning as in this discussion, I think it is advisable
to assume Scala has no such nonsense.
On Nov 17, 2012 4:58 AM, "Soeren Roerden" <soeren.roer...@patch.com> wrote:
> The fact that you can sometimes mix them in Scala is one of the things I
> just find absolutely horrendous. Generically that is completely invalid -
> how would you apply join_M: M M a -> M a to (Monad M, Monad N) => (M N a).
> On Fri, Nov 16, 2012 at 1:57 PM, Lars Hupel <hu...@in.tum.de> wrote:
>> > Yes, you can use the same for-comprehension, but it is *still* valid if
>> you
>> > only change fm to Option[Foo] and keep vm as Identity[Bar].
>> scala> for { foo <- fm; bar <- bm } yield bm + fm.toString
>> <console>:16: error: type mismatch;
>> found : scalaz.Scalaz.Identity[java.lang.String]
>> required: Option[?]
>> for { foo <- fm; bar <- bm } yield bm + fm.toString
>> Apart from that, the misconception that somehow monads allow for
>> different type constructors in a for-comprehension stems from
>> `CanBuildFrom` and the collection library.
>> --
>> You received this message because you are subscribed to the Google Groups
>> "scala-functional" group.
>> To unsubscribe from this group, send email to
>> scala-functional+unsubscribe@googlegroups.com.
> --
> You received this message because you are subscribed to the Google Groups
> "scala-functional" group.
> To unsubscribe from this group, send email to
> scala-functional+unsubscribe@googlegroups.com.
> On 16 November 2012 18:14, Razvan Cojocaru <ra...@razie.com> wrote:
> Interesting - I always thought that you should not be able to change the
shape of the monad, I.e. switching from identity to option... While
composing them.
> I know that scala's for construct allows it as we'll as its collection
library, due to the CanBuildFrom but I didn't think that was kosher.
> I don't think You're not supposed to be able to escape an I/O monad for
instance...
> Also, in my practice, I do avoid for and go to map/flatMap directly as a
matter of preference. They seem to chain and compose more clearly than a
vague for comprehension where everything is in scope...
> Thanks,
> Razvan
> On 2012-11-16, at 11:41 AM, Adam Rosien <a...@rosien.net> wrote:
>> I find that people understand Functor/map() just fine, but when you jump
to Monad/flatMap() (roughly-speaking) nobody really understands the
consequence of flatMap(). But if you show examples using for-comprehensions
then it is much clearer.
>> (Using flatMap() directly is usually a bad code smell in "general" code,
IMHO)
>> I really like Tony's exposition of Monads, using a for-comprehension,
where the comprehension structure *stays the same* while you *vary the
monads used there*, e.g.,
>> the for-comprehension *doesn't need to change*, but *the semantics have
changed*.
>> In other words, you can add *effects* (exception handling via
Option/Either, side-effects via IO, etc.) via (monadic) types, rather than
you needing to "rewrite" your sequence into some other kind of structure.
>> .. Adam
>> On Fri, Nov 16, 2012 at 5:45 AM, Razvan Cojocaru <ra...@razie.com> wrote:
>> I agree with and understand all that, but it feels too abstract and at
the end of the day, my level of understanding was not affected by it. If i
were a newbie (of which I am not far) I would probably have not even
understood what that meant...
>> Thanks,
>> Razvan
>> On 2012-11-16, at 2:33 AM, Karl Roberts <karl.robe...@owtelse.com> wrote:
>>> Hi Razie,
>>> You mention that Monads use flatmap not map... they also have map
because they are also applicative functors which are Functor's which have
map()
>>> Why use use them over the built in abstractions? The pithy answer is
because you can ; -)
>>> But the reason is that every program is a unique specification with its
own abstractions and as such you will undoubtedly have needs that have not
been prepared already for you.
>>> I like the descriptions in "learn you a haskell". Theses higher types
are preserving some context while functions on the values are running. Eg
Option maintains the context if possible failure of a function to provide a
value, and once failed no matter what else you attempt to do to it it stays
failed.
>>> A good question is why would I want my own Monad over and above the
common ones like State or Writer etc?
>>> It is quite easy to think of contexts that are like combinations of the
well known ones eg maintains state and logs what was done, which is a
combination of state and writer. You could build that yourself or look at
monad transformers to create a Frankenstein monad out of the two existing
ones.
>>> You may have a unique context such as testing for compliance to some
constraints as each new bind/flatmap occurs (that may be a combo of state
and Option, say, but may be utterly different).
>>> In any case it is nice to think about the detail of the context you
want to maintain in one place, ie in your monad , than scatter the logic
all through the code everytime some function uses your data structures.
>>> Hope I didn't waffle too much.
>>> Cheers
>>> Karl
>>> On Nov 14, 2012 4:08 AM, "Razvan Cojocaru" <ra...@razie.com> wrote:
>>> So… how off am I in the pictures I was trying to paint below?
>>> Are these worth painting ? I keep struggling to explain monads and
their brethren in simpler terms…
>>> Cheers/thanks,
>>> Razie
>>> From: Razvan Cojocaru [mailto:p...@razie.com]
>>> Sent: November-12-12 10:02 PM
>>> To: 'Zachary Abbott'; scala-user@googlegroups.com
>>> Subject: RE: [scala-user] Scala and Monads. Why and when to use them
over other abstractions.
>>> I will be necessarily somewhat long, somewhat wrong and mostly fuzzy,
given my current level of understanding, but I am not one to shy away from
making a fool of oneself J If my current understanding is wrong, I can’t
wait to be corrected!
>>> Monads (and related concepts from category theory like Functor,
Applicative etc) are the next level of abstraction beyond functions…
>>> Functions f : A => B allow you to think and program in a certain way.
Once you get used to this “functional programming” you can move on to
higher types and higher functions and from there to monads.
>>> For instance, Functors F [A] lift a simple function to something more
– the signature tells you their secret
>>> map (f : A => B) : F[A] => F[B]
>>> …they essentially gobble up your function f and return something lazy
and higher level – think about that for a second. The laziness aspect of it
is not that important at this point.
>>> MAP - you could think of it as taking a simple unix command like “wc
-l” and apply it to something “a | wc” where a could be the result of “find
*.txt”… I still see it that way after many years…
>>> In scala you use a slightly different version of the same idea
List(1,2,3) map (_ + 4).
>>> Why are they useful? Many reasons
>>> For instance – you are normally ‘forbidden’ from using state between
two calls to f – you should know that by now. However, INSIDE A FUNCTOR,
you could, for the duration of the entire transformation F[A] => F[B]… you
could have some state there… this is the beauty of an internalized iterator
versus the one you’re used to. That state would be **well encapsulated**
there in that transformation, so it could be used.
>>> How that transformation is executed, is up to the specific functor you
use. Some can optimize it, some can be dumb while some can use state (like
cache a DB connection between calls or whatever).
>>> Let’s have a quick random example: I could have my own functor, working
on lists, which keeps the elements sorted. If I apply a random function to
it, the result has to be also sorted. You can see the problem? my functor
will keep it sorted while an externalized loop may or may not keep it
sorted, depending on the programmer.
>>> MySortedList (1,2,3) map (rand(_)) will always be sorted,
while List (1,2,3) map (rand(_)) is not…
>>> Without functions and functors, there is no way you could express and
enforce that idea – I don’t think…
>>> Monads go even further. Monads have certain laws which give them
certain properties which are very useful once you get used to thinking in
those terms.
>>> Monads use flatMap rather than map, with a signature
>>> flatMap (f:A=>M[B]) : M[A] => M[B]
>>> as you can see, they also return a transformation, but a higher level
one, which include flattening. But because it INCLUDES flattening, it can
do it in whichever way it wants.
>>> Why monads are more useful than functors – look at the gobble-able
it’s an f : A => M[A] rather than f : A => B – the functors limit you to
the shape of the functor, sort of speak – basically if you start with a
...