
The point of concepts like functors, monoids, and monads is not because they
provide functionality that wouldn't normally be accessible, but for the
following reasons:
1. The concept encapsulates a huge number of common programming idioms.
Indicating that a concept fits the functor, monad, or monoid paradigm
provides the advantages that
a) significant repeated code can be scrapped in favor of general library
code. Writing "mconcat" is much nicer than writing "foldr (++) []", though
perhaps lists aren't the best example (due to the presence of just plain
"concat").**
b) Using fully general, well-known (within the Haskell community)
abstractions provides other programmers with easily read hints about the
behavior of your code, such as the indication that a Foo can be composed
with another Foo in an associative fashion, so parentheses are irrelevant.
(So foldl mappend mzero ls is equivalent to foldr mappend mzero ls, but the
latter fuses more powerfully without stream fusion.)
2. Very abstract, very general typeclasses in libraries come with very
general combinators and functions in libraries, with the bonus that GHC's
optimizer is almost always capable of optimizing code using these general
structures into code just as, or very nearly as, good as equivalent code
that would take you hours to write and would considerably obfuscate the
programmer's actual intention.
3. Writing code in a very general, abstract fashion can considerably improve
the *developer*'s thinking about the program. As an example, this weekend I
was playing with (very, very custom-tuned) monads to fill up the contents of
an array in several different fashions, and taught myself monad transformers
as a very elegant way to encapsulate a shared, universal array, a mutable
index state, and successive (associative and commutative) operations on a
State; this went through several permutations (and is still in progress).
As an additional observation, using the Sum, Product, Any, and other similar
monoids, when done appropriately and mconcat'd, gives no actual overhead due
to standard optimizations (in particular, each of them is a newtype).
That's to say that I'm almost positive that mconcat (map Product ls) is
equivalent to foldMap
Louis Wasserman
wasserman.louis@gmail.com
On Sat, Jan 17, 2009 at 10:46 AM,
Send Haskell-Cafe mailing list submissions to haskell-cafe@haskell.org
To subscribe or unsubscribe via the World Wide Web, visit http://www.haskell.org/mailman/listinfo/haskell-cafe or, via email, send a message with subject or body 'help' to haskell-cafe-request@haskell.org
You can reach the person managing the list at haskell-cafe-owner@haskell.org
When replying, please edit your Subject line so it is more specific than "Re: Contents of Haskell-Cafe digest..."
Today's Topics:
1. Re: Comments from OCaml Hacker Brian Hurt (david48) 2. Re: Re: Comments from OCaml Hacker Brian Hurt (david48) 3. Re: Comments from OCaml Hacker Brian Hurt (Andrew Coppin) 4. Re: some ideas for Haskell', from Python (Artyom Shalkhakov) 5. Re: Comments from OCaml Hacker Brian Hurt (Andrew Coppin) 6. Re: Re: Comments from OCaml Hacker Brian Hurt (Eugene Kirpichov) 7. Re: Comments from OCaml Hacker Brian Hurt (Eugene Kirpichov) 8. Functors [Comments from OCaml Hacker Brian Hurt] (Andrew Coppin) 9. Re: Functors [Comments from OCaml Hacker Brian Hurt] (Eugene Kirpichov) 10. Re: Functors [Comments from OCaml Hacker Brian Hurt] (Luke Palmer) 11. Re[2]: [Haskell-cafe] Functors [Comments from OCaml Hacker Brian Hurt] (Bulat Ziganshin) 12. Re: Re[2]: [Haskell-cafe] Comments from OCaml Hacker Brian Hurt (David Leimbach) 13. OS X build failure of Gtk2Hs from MacPorts (Jeff Heard) 14. Re: Comments from OCaml Hacker Brian Hurt (Lennart Augustsson) 15. Re: Comments from OCaml Hacker Brian Hurt (David Leimbach) 16. Re: ANN: HTTPbis / HTTP-4000.x package available (Tim Newsham) 17. Efficient Factoring Out of Constants (Phil) 18. Re: Efficient Factoring Out of Constants (Luke Palmer)
----------------------------------------------------------------------
Message: 1 Date: Sat, 17 Jan 2009 10:47:56 +0100 From: david48
> Subject: Re: [Haskell-cafe] Comments from OCaml Hacker Brian Hurt To: "Jonathan Cast" Cc: haskell-cafe@haskell.org Message-ID: <4c88418c0901170147u3e0a3d65r2ab72d9bbc8cb1e6@mail.gmail.com> Content-Type: text/plain; charset=UTF-8 On Fri, Jan 16, 2009 at 4:04 PM, Jonathan Cast
wrote: On Fri, 2009-01-16 at 14:16 +0100, david48 wrote:
Part of the problem is that something like a monoid is so general that I can't wrap my head around why going so far in the abstraction. For example, the writer monad works with a monoid; using the writer monad with strings makes sense because the mappend operation for lists is (++), now why should I care that I can use the writer monad with numbers which it will sum ?
To accumulate a running count, maybe? A fairly common pattern for counting in imperative languages is
int i = 0; while (<get a value>) i+= <count of something in value>
Using the writer monad, this turns into
execWriter $ mapM_ (write . countFunction) $ getValues
well thank you for the example, if I may ask something: why would I need to write a running count this way instead of, for example, a non monadic fold, which would probably result in clearer and faster code (IMHO) ?
------------------------------
Message: 2 Date: Sat, 17 Jan 2009 11:08:25 +0100 From: david48
> Subject: Re: [Haskell-cafe] Re: Comments from OCaml Hacker Brian Hurt To: "Apfelmus, Heinrich" Cc: haskell-cafe@haskell.org Message-ID: <4c88418c0901170208i74358328ycaa10359fb639873@mail.gmail.com> Content-Type: text/plain; charset=UTF-8 On Fri, Jan 16, 2009 at 10:28 PM, Apfelmus, Heinrich
wrote: david48 wrote:
I don't care about the name, it's ok for me that the name mathematicians defined is used, but there are about two categories of people using haskell and I would love that each concept would be adequately documented for everyone: - real-world oriented programming documentation with usefulness and examples for the non mathematician - the mathematics concepts and research papers for the mathematicians for those who want/need to go further
As someone mentionned, the documentation can't really be done by someone that doesn't fully grok the concepts involved.
Good account of the current documentation situation.
Hm, what about the option of opening Bird's "Introduction on Functional Programming using Haskell" in the section about fold? Monoid is on page 62 in the translated copy I've got here.
I don't have this book. I have real world haskell and purely functional data structures though.
Does Hutton's book mention them? Real World Haskell?
the first time it is mentionned in RWH according to the index is page 266 where we read "We forgot to test the Monoid instance" ... "...of Monoid, which is the class of types that support appending and empty elements:"
Appending.... :)
On the other hand, on page 320 there is a nice explanation of Monoid, and on page 380, which isn't mentionned in the index, there might be the first time one can understand why the writer monad works with monoids instead of lists: to be able to use better suited data types for appending.
All of this is still lacking the great why : why/how an abstraction so generic can be useful. I'm starting to believe that the only reason to make a datatype an instance of Monoid is... why not ! since it's not hard to find an associative operation and a neutral element.
I don't think that I would try to learn a programming language, for example Python, without obtaining a paper book on it.
I would, if the online documentation makes it possible, and then I would buy a paper book later, to go further or for reference. That's how I learned Haskell, and much later I've bought my first book.
------------------------------
Message: 3 Date: Sat, 17 Jan 2009 11:07:03 +0000 From: Andrew Coppin
Subject: Re: [Haskell-cafe] Comments from OCaml Hacker Brian Hurt To: haskell-cafe@haskell.org Message-ID: <4971BBD7.504@btinternet.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Anton van Straaten wrote:
Niklas Broberg wrote:
I still think existential quantification is a step too far though. :-P
Seriously, existential quantification is a REALLY simple concept, that you would learn week two (or maybe three) in any introductory course on logic. In fact, I would argue that far more people probably know what existential quantification is than that know what a monoid is. :-)
Andrew's core objection here seems reasonable to me. It was this:
{-# LANGUAGE ExistentialQuantification #-} is an absurd name and should be changed to something that, at a minimum, tells you it's something to do with the type system.
But I suspect I part company from Andrew in thinking that something like ExistentiallyQuantifiedTypes would be a perfectly fine alternative.
I would suggest that ExistentiallyQuantifiedTypeVariables would be an improvement on just ExistentialQuantification - but I'd still prefer the less cryptic HiddenTypeVariables. (Since, after all, that's all this actually does.)
Either way, nobody is going to change the name, so why worry?
PS. There exist courses on logic? That could be potentially interesting...
------------------------------
Message: 4 Date: Sat, 17 Jan 2009 17:12:14 +0600 From: Artyom Shalkhakov
Subject: Re: [Haskell-cafe] some ideas for Haskell', from Python To: Immanuel Litzroth , haskell-cafe@haskell.org Message-ID: <2076f2f90901170312y7e6dfa36jf61ab2f67f1c454a@mail.gmail.com> Content-Type: text/plain; charset=UTF-8 Hello,
2009/1/16 Immanuel Litzroth
: I don't understand your comment. 1) If XMonad already uses it the problem is solved, without giving Haskell import new semantics?
Right, but there are some restrictions.
2) These guys refer to a method to do plugin work in Haskell http://www.cse.unsw.edu.au/~dons/hs-plugins/http://www.cse.unsw.edu.au/%7Edons/hs-plugins/ So the problem of dynamically loading plugins should already be solved?
Well, mostly yes, but I think that it should be added to the language.
Cheers, Artyom Shalkhakov.
------------------------------
Message: 5 Date: Sat, 17 Jan 2009 11:17:12 +0000 From: Andrew Coppin
Subject: Re: [Haskell-cafe] Comments from OCaml Hacker Brian Hurt To: haskell-cafe@haskell.org Message-ID: <4971BE38.9060002@btinternet.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Cory Knapp wrote:
Actually, that was part of my point: When I mention Haskell to people, and when I start describing it, they're generally frightened enough by the focus on pure code and lazy evaluation-- add to this the inherently abstract nature, and we can name typeclasses "cuddlyKitten", and the language is still going to scare J. R. Programmer. By "inherently mathematical nature", I didn't mean names like "monoid" and "functor", I meant *concepts* like monoid and functor. Not that either of them are actually terribly difficult; the problem is that they are terribly abstract. That draws a lot of people (especially mathematicians), but most people who aren' drawn by that are hugely put off-- whatever the name is. So, I guess my point is that the name is irrelevant: the language is going to intimidate a lot of people who are intimidated by the vocabulary.
Oh, I don't know. I have no idea what the mathematical definition of "functor" is, but as far as I can tell, the Haskell typeclass merely allows you to apply a function simultaneously to all elements of a collection. That's pretty concrete - and trivial. If it weren't for the seemingly cryptic name, nobody would think twice about it. (Not sure exactly what you'd call it though...)
A monoid is a rather more vague concept. (And I'm still not really sure why it's useful on its own. Maybe I just haven't had need of it yet?)
I think, as somebody suggested about "monad", the name does tend to inspire a feeling of "hey, this must be really complicated" so that even after you've understood it, you end up wondering whether there's still something more to it than that.
But yes, some people are definitely put off by the whole "abstraction of abstractions of abstraction" thing. I think we probably just need some more concrete examples to weight it down and make it seem like something applicable to the real world.
(Thus far, I have convinced exactly *one* person to start learning Haskell. This person being something of a maths nerd, their main complaint was not about naming or abstraction, but about the "implicitness" of the language, and the extreme difficulty of visually parsing it. Perhaps not surprising comming from a professional C++ programmer...)
At the same time, I think everyone is arguing *for* better documentation. And you're probably right: better documentation will bring the abstract nonsense down to earth somewhat.
Amen!
------------------------------
Message: 6 Date: Sat, 17 Jan 2009 14:27:02 +0300 From: "Eugene Kirpichov"
Subject: Re: [Haskell-cafe] Re: Comments from OCaml Hacker Brian Hurt To: david48 > Cc: "Apfelmus, Heinrich" , haskell-cafe@haskell.org Message-ID: <5e0214850901170327t13bd62ds75167a28f68ed39c@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1 The great "that's why" is as follows: when you have an abstraction, then it is sufficient to hold the abstraction in mind instead of the whole concrete implementation. That's the whole purpose of abstraction, after all, be it maths or programming.
Let me illustrate this.
Suppose you are developing a library that, for instance, has a notion of "settings" and is able to combine two "settings" with several strategies for resolving conflicts between settings with duplicate keys: take the first setting, the second, none, or make a setting with multiple values. For example, an alternative GetOpt.
Suppose you don't know what a monoid is and don't even know that such an abstraction exists. Now, when you're reasoning about the library, you have to think "If I combine 3 settings, should the order of combination matter? Hmm, would be nice if it didn't. Also, what should I return if someone queries for a non-existent key in the settings? Should I return an empty list, or a Nothing, or throw an error, or what? Do empty settings make sense?" etc. If you're smart and lucky, you will most probably get most things right and inconsciously create a settings monoid.
Now, if you know what a monoid is, you immediately recognize that your settings should be a monoid by nature, and now you have absolutely no doubt that you should make the combining operation associative and provide a unit; and you use this monoid abstraction all the time you are designing this library. Now, you don't think about whether you should throw an error or return a Nothing for an empty key; but instead you think about which result would behave like a unit for the monoid, being motivated by mathematical principles rather than pure intuition.
You end up designing a mathematically sound library whose principles make sence and has no design flaws, at least in the mathematically sound part, even if you never actually use the word "monoid" in the documentation.
Also, read this post by sigfpe that motivated me to learn abstract algebra in depth (I am yet in the beginning, however), and, overall, this is a breathtaking post:
http://sigfpe.blogspot.com/2008/11/approach-to-algorithm-parallelisation.htm... - this is where I started to appreciate the power of mathematical abstractions even more.
2009/1/17 david48
: All of this is still lacking the great why : why/how an abstraction so generic can be useful. I'm starting to believe that the only reason to make a datatype an instance of Monoid is... why not ! since it's not hard to find an associative operation and a neutral element.
-- Eugene Kirpichov
------------------------------
Message: 7 Date: Sat, 17 Jan 2009 14:34:25 +0300 From: "Eugene Kirpichov"
Subject: Re: [Haskell-cafe] Comments from OCaml Hacker Brian Hurt To: "Andrew Coppin" Cc: haskell-cafe@haskell.org Message-ID: <5e0214850901170334u27f17902nc56d0002f4702f06@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1 Cory Knapp wrote:
Actually, that was part of my point: When I mention Haskell to people,
and
when I start describing it, they're generally frightened enough by the focus on pure code and lazy evaluation-- add to this the inherently abstract nature, and we can name typeclasses "cuddlyKitten", and the language is still going to scare J. R. Programmer. By "inherently mathematical nature", I didn't mean names like "monoid" and "functor", I meant *concepts* like monoid and functor. Not that either of them are actually terribly difficult; the problem is that they are terribly abstract. That draws a lot of
2009/1/17 Andrew Coppin
: people (especially mathematicians), but most people who aren' drawn by that are hugely put off-- whatever the name is. So, I guess my point is that the name is irrelevant: the language is going to intimidate a lot of people who are intimidated by the vocabulary.
Oh, I don't know. I have no idea what the mathematical definition of "functor" is, but as far as I can tell, the Haskell typeclass merely allows you to apply a function simultaneously to all elements of a collection. That's pretty concrete - and trivial. If it weren't for the seemingly cryptic name, nobody would think twice about it. (Not sure exactly what you'd call it though...)
No, a functor is a more wide notion than that, it has nothing to do with collections. An explanation more close to truth would be "A structure is a functor if it provides a way to convert a structure over X to a structure over Y, given a function X -> Y, while preserving the underlying 'structure'", where preserving structure means being compatible with composition and identity.
Collections are one particular case.
Another case is just functions with fixed domain A: given a "structure" of type [A->]X and a function of type X -> Y, you may build an [A->]Y.
Yet another case are monads (actually, the example above is the Reader monad): given a monadic computation of type 'm a' and a function a -> b, you may get a computation of type m b:
instance (Monad m) => Functor m where fmap f ma = do a <- ma; return (f a)
There are extremely many other examples of functors; they are as ubiquitous as monoids and monads :)
-- Eugene Kirpichov
------------------------------
Message: 8 Date: Sat, 17 Jan 2009 12:04:01 +0000 From: Andrew Coppin
Subject: [Haskell-cafe] Functors [Comments from OCaml Hacker Brian Hurt] To: haskell-cafe@haskell.org Message-ID: <4971C931.2070202@btinternet.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Eugene Kirpichov wrote:
No, a functor is a more wide notion than that, it has nothing to do with collections. An explanation more close to truth would be "A structure is a functor if it provides a way to convert a structure over X to a structure over Y, given a function X -> Y, while preserving the underlying 'structure'", where preserving structure means being compatible with composition and identity.
As far as I'm aware, constraints like "while preserving the underlying structure" are not expressible in Haskell.
instance (Monad m) => Functor m where fmap f ma = do a <- ma; return (f a)
While that's quite interesting from a mathematical point of view, how is this "useful" for programming purposes?
------------------------------
Message: 9 Date: Sat, 17 Jan 2009 15:12:26 +0300 From: "Eugene Kirpichov"
Subject: Re: [Haskell-cafe] Functors [Comments from OCaml Hacker Brian Hurt] To: "Andrew Coppin" Cc: haskell-cafe@haskell.org Message-ID: <5e0214850901170412j12536846r91f7dc58d8b8f806@mail.gmail.com> Content-Type: text/plain; charset=ISO-8859-1 2009/1/17 Andrew Coppin
: Eugene Kirpichov wrote:
No, a functor is a more wide notion than that, it has nothing to do with collections. An explanation more close to truth would be "A structure is a functor if it provides a way to convert a structure over X to a structure over Y, given a function X -> Y, while preserving the underlying 'structure'", where preserving structure means being compatible with composition and identity.
As far as I'm aware, constraints like "while preserving the underlying structure" are not expressible in Haskell.
Yes, but they are expressible in your mind so that you can recognize a functor and design you program so that it does satisfy this constraint, thus removing a large faulty piece of the design space.
Also, you can write a QuickCheck test for fmap (f . g) = fmap f . fmap g and fmap id = id.
instance (Monad m) => Functor m where fmap f ma = do a <- ma; return (f a)
While that's quite interesting from a mathematical point of view, how is this "useful" for programming purposes?
In the same sense as monoids are, see my previous message.
If you mean the usefulness of a Functor typeclass in Haskell, it's in the fact that everywhere where you'd like to convert a structure over X to a structure over Y (for example, the result of a monadic computation), you simply write 'fmap f structure' and it works the right way, if the structure has an instance for Functor (many structures do). I know I'm being a bit abstract, but that's the way I percept it.
do filename <- toLowerCase `fmap` readLine ....
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
------------------------------
Message: 10 Date: Sat, 17 Jan 2009 05:16:06 -0700 From: Luke Palmer
Subject: Re: [Haskell-cafe] Functors [Comments from OCaml Hacker Brian Hurt] To: Andrew Coppin Cc: haskell-cafe@haskell.org Message-ID: <7ca3f0160901170416n28e822c1t5cd693d61f9446a3@mail.gmail.com> Content-Type: text/plain; charset="iso-8859-1" On Sat, Jan 17, 2009 at 5:04 AM, Andrew Coppin
wrote: Eugene Kirpichov wrote:
No, a functor is a more wide notion than that, it has nothing to do with collections. An explanation more close to truth would be "A structure is a functor if it provides a way to convert a structure over X to a structure over Y, given a function X -> Y, while preserving the underlying 'structure'", where preserving structure means being compatible with composition and identity.
As far as I'm aware, constraints like "while preserving the underlying structure" are not expressible in Haskell.
Well, they're expressible *about* Haskell. I.e., for functors we require:
fmap id = id fmap (f . g) = fmap f . fmap g
The first property is how we write "preserving underlying structure", but this has a precise, well-defined meaning that we can say a given functor obeys or it does not (and if it does not, we say that it's a bad instance). But you are correct that Haskell does not allow us to require proofs of such properties.
And indeed, some people break those properties in various ways, which some consider okay if the breakage is not observable from outside a given abstraction barrier. I'm on the fence about that...
Luke
participants (1)
-
Louis Wasserman