[Haskell-cafe] Monad Description For Imperative Programmer
This is about to put a definition/description to test. So please cooperate! ;) Is this a useful – sufficient, not complete – definition/description for a monad; for an imperative mind: (?) "A monad is like a loop that can run a new function against it's variable in each iteration." (I insist on the simplicity! And I will resist any expansion of this sentence (except for an exceptional note that I think of it hardly). I think there is not any complete definitions in computer world. At least there are many things to know when you want to use them in practice. So please have this in mind and review me!) Cheers :) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On Wednesday 01 August 2007 17:02, Kaveh Shahbazian wrote: > This is about to put a definition/description to test. So please cooperate! > ;) > Is this a useful – sufficient, not complete – definition/description for a > monad; for an imperative mind: (?) > > "A monad is like a loop that can run a new function against it's variable > in each iteration." At least in the context of Haskell, that's not correct. For a recent discussion about a simple definition of Haskell monads, see the thread beginning at: http://permalink.gmane.org/gmane.comp.lang.haskell.cafe/25882 Alexis. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 01/08/07, Andrew Wagner <[EMAIL PROTECTED]> wrote: > This seems wrong to me. A monad is, first and foremost, a type > constructor class. I'm not sure how you can really compare that to a > loop. But perhaps the easiest way to test your definition would be to > ask this: How is, for example, the Maybe monad like a loop, in your > definition? I am baffled by this discussion. I thought monads were something to do with boxes of toxic apples in space? Obviously we can relate monadic apples to arrows through the William Tell analogy. And erm... yeah. Still needs a little polishing. I just hope the whole metaphor isn't rotten to the core. I will be here all week. Please, try the spice cake. Cheers, D. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
This seems wrong to me. A monad is, first and foremost, a type constructor class. I'm not sure how you can really compare that to a loop. But perhaps the easiest way to test your definition would be to ask this: How is, for example, the Maybe monad like a loop, in your definition? On 8/1/07, Kaveh Shahbazian <[EMAIL PROTECTED]> wrote: > This is about to put a definition/description to test. So please cooperate! > ;) > Is this a useful – sufficient, not complete – definition/description for a > monad; for an imperative mind: (?) > > "A monad is like a loop that can run a new function against it's variable in > each iteration." > > (I insist on the simplicity! And I will resist any expansion of this > sentence (except for an exceptional note that I think of it hardly). > I think there is not any complete definitions in computer world. At least > there are many things to know when you want to use them in practice. So > please have this in mind and review me!) > > Cheers :) > > > ___ > Haskell-Cafe mailing list > Haskell-Cafe@haskell.org > http://www.haskell.org/mailman/listinfo/haskell-cafe > > ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 8/1/07, Andrew Wagner <[EMAIL PROTECTED]> wrote: > This seems wrong to me. A monad is, first and foremost, a type > constructor class. I'm not sure how you can really compare that to a > loop. But perhaps the easiest way to test your definition would be to > ask this: How is, for example, the Maybe monad like a loop, in your > definition? As a beginner haskeller coming from an imperative experience, I think I understood what he meant. say you have this code : putStrLn "1" >> putStrLn "2" >> putStrLn "3" you can imagine each of the calls to putStrLn gets implicitly passed a variable (here, the world ) and they happen in succession so it's "like a loop". Except that a loop... loops so the comparison is far fetched. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 8/1/07, Andrew Wagner <[EMAIL PROTECTED]> wrote: > > you can imagine each of the calls to putStrLn gets implicitly passed a > > variable (here, the world ) and they happen in succession so it's > > "like a loop". > It breaks down further as soon as you add any amount of complexity to > the code as well. E.g.: [] > Not loop-ish at all! I totally agree I was just stating how I understood the original poster's statement :) Personally I showed haskell to a Friend last week end. To explain some monadic code I explained it somewhat this way ( please keep in mind that I'm a beginner so the explanation I gave him is probably not accurate ) I told him that in a lazy functional programming language you can't decide when a function gets evaluated or not. I then told him that it gets problematic if you want evaluate some functions in sequence. I also told him that haskell is a pure language, that is there is no side effects in the functions. I then told him that it's a problem if you want to interact with the outside world (IO) I explained that a monad is a way to get functions evaluated in a specific order, with a type such that you can't mix actions with pure functions. I told him that monads are just a special datatype and implementation of 2 functions : - a function that lets you evaluate a function before evaluating the next one, taking the output of the first function to feed the input of the second. - a function that takes a pure value and "promotes" to the monad's type. I told him that in the case of IO the datatype in question is IO and it contains data about the outside world, but there are many other monads, but I didn't go there too much because it's not totally clear for me. He seemed to be not too much confused by the concept, so I hope that I didn't told him too much inaccuracies... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 8/1/07, david48 <[EMAIL PROTECTED]> wrote: > As a beginner haskeller coming from an imperative experience, I think > I understood what he meant. > > say you have this code : > >putStrLn "1" >> putStrLn "2" >> putStrLn "3" > > you can imagine each of the calls to putStrLn gets implicitly passed a > variable (here, the world ) and they happen in succession so it's > "like a loop". Why isn't this "like a semicolon"? Chris ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
> say you have this code : > >putStrLn "1" >> putStrLn "2" >> putStrLn "3" > > you can imagine each of the calls to putStrLn gets implicitly passed a > variable (here, the world ) and they happen in succession so it's > "like a loop". It breaks down further as soon as you add any amount of complexity to the code as well. E.g.: putStrLn "1" >> getLine >>= \line -> putStrLn line >> putStrLn "end" This prints something, gets something from the user and prints it, and then prints something else. The equivalent imperative pseudo-code is something like: print "foo"; line = inputLine(); print line; print "end"; Not loop-ish at all! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
My own perspective on monads is this: In procedural and OO languages, when dealing with compound data structures, we think in terms of getters (*taking data out* of the structure) and setters (*putting data in* to the structure). Languages with some impure functional features (Lisp, Scheme, Perl, Python) let you operate on lists with a "map" function ("mapcar" in Common Lisp), where instead of *taking data out* of a list, you *put a function in*, and the function manipulates each element without being aware of the context. You *turn the data structure inside-out*, as it were, so you don't have to think about how the elements are accessed. Functors are a generalization from lists to "things that can be mapped over" in general, and then monads are a generalization of functors. Haskell solves the "how can I do I/O in a pure functional language" problem by *turning the world inside-out*. Instead of taking data from the mutable outside world, using functions to manipulate it, and depositing results back into that world, you put your functions into the IO monad. It's like the joke about how a theoretical mathematician catches an elephant: build a cage, go inside, close the door, and redefine outside as inside. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE [Haskell-cafe] Monad Description For Imperative Programmer
> How does all this map to C++? A monad is a a class, with no useful > interface for the end user, that looks roughly (i.e. I haven't tested > it) like: trying to implement it in other languages is a good idea for understanding monads. I've tried this with the Maybe monad in Lisp: http://groups.google.com/group/comp.lang.lisp/msg/3bd8ecfb6cfd6601 There are other tries in Scheme and Lisp, even a general Arrows approach IIRC. -- Frank Buss, [EMAIL PROTECTED] http://www.frank-buss.de, http://www.it4-systems.de ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On Thursday 02 August 2007 08:17, Claus Reinke wrote: > a Monad is a type constructor with two operations, implementing > a standard interface and following a few simple rules. . . . . and this is one of the best definitions i've seen yet. Thanks Claus! i think we need to be looking at "What is a Monad?" issue from the point of view of putting together a Dictionary of Haskell. There's no room for long explanations - just a concise sentence or two that gets to the heart of what a Haskell Monad is. Personally, my feeling is that people are scared by Monads, not because of the name, but because whenever they ask about what a Monad essentially /is/, they get a plethora of less-than-concise explanations that often don't include the sort of straightforward starting definition than Claus has presented here. No wonder Monads seem scary when even experienced Haskell programmers put forward such a variety of attempts to describe what a Monad actually is! (In some ways, i'm reminded of discussions about what continuations are - many definitions are vague and involve hand-waving; only a few seem to provide a straightforward technical definition that doesn't skirt around the guts of the matter.) That's why i've banged on about presenting my own attempt at a concise definition - not because i think my definition is that great at all, but because it at least represents a starting point to work towards developing a concise definition that we can quote and /then/ elaborate on in the way that we think is most likely to convey how Monads work to the querent in question. And again, i really like Claus' elaboration: > the Monad type class tells you the interface (what operations > you've got, and their types), the Monad laws tell you what all > types implementing that interface should have in common. > > the monadic interface gives you two operations, one to throw > things into a monad thing (return), and one to chain two monad > things together (>>=). the chaining explicitly caters for information > flowing from the first to the second parameter of (>>=). > > the monad laws tell you two useful facts about monad things > thrown together in that way: whatever it is the monad does, > anything just thrown into it will take no part in that action, > and whichever way you use that chaining operation, the > structure of chaining is irrelevant, only the ordering of chained > monad things matters. > > there are usually other ways to create 'primitive' monadic things, > which can be combined into complex monadic structures using > the operations from the Monad interface. > > there is usually a way to interpret monadic structures built in > this way (a 'run' operation of some kind). Category theorists can define monads concisely using the language of their discipline - surely we can settle on a definition of Haskell Monads that would make sense to any programmer who has mastered basic programming concepts? i would suggest that Claus' definition, above, would be a great place to start. :-) Alexis. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
Someone asked about comparing monads to loops. If you are chiefly familiar with the i/o and state monads, that doesn't really make a lot of sense, but there IS a use of monads which IS a kind of loop. Only yesterday I was trying to read someone else's Haskell code where they had imported Control.Monad for the sake of >>= and liftM2. And how were they using >>= and liftM2? - they were using >>= on lists, where it means the same as concatMap To a beginner, I suggest that (concatMap f xs) is clearer than (xs >>= f) - they were using (liftM2 f xs ys) on lists, where it means the same as [f x y | x <- xs, y <- ys] No doubt there are people who find the monadic versions clearer. However, since the monadic operations *ARE* loops when applied to lists, it could very easily give rise to the misunderstanding that monads have something to do with looping. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 2 Aug 2007, at 1:20 pm, Alexis Hazell wrote: Category theorists can define monads concisely using the language of their discipline - surely we can settle on a definition of Haskell Monads that would make sense to any programmer who has mastered basic programming concepts? It all depends on what you mean "make sense to". I can tell my student that (an instance of Monad) is a type constructor applications of which support certain operations that must satisfy certain operations. They can memorise that. But it remains meaningless noise to them. What matters is not what monads *ARE* but what they are *FOR*. Why should anyone care what monads are until they know why monads matter? One of my colleagues here, who has worked in logic for many years, is fond of saying that there are "set theory" people who like to have their feet on the ground and "category theory" people who like to have their heads in the air. There's no dispute that you get a much better view with your head in the air; there is no dispute that the general definitions and understandings of monads have power and utility. Me, I'm a set theory person. I have no trouble with fields, got my head around tensors and Lie groups (or very nearly), and I even know what a fibre bundle is (got an A for that). All of this is *grounded*. But I have repeatedly hit category theory and as repeatedly bounced. Chapter 1? No trouble. Chapter 2? No trouble. Chapter 3? Bounce. If a "category theory" person wants to understand monads, they will be happy with an abstract approach and work down from there. But if a "set theory" person wants to understand monads, they have to start with simple specific cases. The IO monad first. The ST monad. Then perhaps Maybe and []. And then start learning about monad transformers. The understanding of monads as such will grow out of this; by the time they are ready to cope with these compact high level definitions people are talking about they won't need it any more. I don't have any numbers. It would be interesting if someone did a survey. But I suspect that "category theory" people are a minority even among functional programmers. How many O'Caml programmers worry about the definition of monads? So go on arguing about how to define monads for Haskell, but consider your audience. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On Thursday 02 August 2007 15:57, ok wrote: > It all depends on what you mean "make sense to". > I can tell my student that (an instance of Monad) is a type constructor > applications of which support certain operations that must satisfy > certain operations. They can memorise that. But it remains meaningless > noise to them. What matters is not what monads *ARE* but what they are > *FOR*. Why should anyone care what monads are until they know why monads > matter? Well, i would argue that people learning Haskell come to quite quickly appreciate that these 'monad' things are very important in Haskell; that they have to learn about them in order to perform IO and maintain state[1]; and that it's for those reasons at least that they matter. In my experience, many programmers - including myself! :-) - then try to get their head around what a Haskell Monad "is", and start asking questions of more experienced Haskellers, trying to get some sense of a possible answer. It's at this point that i feel there's an issue. Haskell Monads are used FOR many many things. And rather than get to the core of what a Monad is, many people provide two or three motivating examples - examples which merely serve to show /some/ of what Monads are about, but which will lead astray any person who incorrectly assumes that these two or three examples constitute the totality of the Monadic universe, and who makes inferences about Monads accordingly. (To me, the notion that a Monad is merely a kind of loop is an example of this.) This is why i feel it's important to provide an agreed-upon minimalist definition of a Monad - it can serve as a /correct/ starting point (to be elaborated on, of course - as Claus did), rather than forcing the programmer new to Haskell to /guess/ what a Monad might "be". We keep trying to suggest that Monads aren't really that scary, but the fact that we can't seem to agree upon a straightforward definition of what a Monad "is" belies that - i feel it tends to convey that in fact Monads /are/ a very complex concept, that asking what Monads are is like asking what God is or something. :-P And in my opinion, feeling that a given topic is overwhelming complex can become a block to further learning. Alexis. [1] Yes, they're obviously used for many other things besides those two things; but it's these two cases that are often of most interest to programmers coming from a non-functional background. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 02/08/07, Alexis Hazell <[EMAIL PROTECTED]> wrote: > It's at this point that i feel there's an issue. Haskell Monads are used FOR > many many things. And rather than get to the core of what a Monad is, many > people provide two or three motivating examples - examples which merely serve > to show /some/ of what Monads are about, but which will lead astray any > person who incorrectly assumes that these two or three examples constitute > the totality of the Monadic universe, and who makes inferences about Monads > accordingly. (To me, the notion that a Monad is merely a kind of loop is an > example of this.) I agree with this very much. Monads are used for a great deal of things, some of which seem related (IO/State, []/Maybe) while others are utterly disconnected. Simon Peyton Jones has jokingly said that "warm fuzzy things" would have been a better choice of name. In seriousness, though, I think the exact name is not the problem. I would suggest that *having a name* is the problem. In imperative programming there are many idioms we would recognise. Take the "do something to an array" idiom: for (int i = 0; i < arr.length; i++) { arr[i] = foo(arr[i]); } This is a pretty obvious pattern. Some might say it's so obvious that it doesn't need a name. Yet we've got one in functional programming because we can. Without higher-order functions it's not possible to encapsulate and name such common idioms. It seems a bit superfluous to name something if you can't do anything with the name. But with higher-order functions we *can* encapsulate these ideas, and that means we *must* name them. Add to that the insatiable mathematical desire to abstract, abstract, abstract... Intuitively it seems that monads are similar, except the instances are much less obviously connected. It's easy to see the connection between State and IO. But those two to []? Do I have an suggestions? Well, maybe the right way would be to do as we do with map and fold, etc: show the explicitly recursive example, then generalise. So, show how we could we would thread state in Haskell, or how we would do optional (Maybe-style) values, then generalise, *slowly* coalescing the more similar monads first before reaching the 'top' of the monadic phylogenetic tree. Hmm, I can see that previous paragraph is not as clear as it could be. But anyway: has anyone used this approach before? Cheers, D. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 8/2/07, Seth Gordon <[EMAIL PROTECTED]> wrote: > Haskell solves the "how can I do I/O in a pure functional language" > problem by *turning the world inside-out*. Instead of taking data from > the mutable outside world, using functions to manipulate it, and > depositing results back into that world, you put your functions into the > IO monad. That's a very interesting perspective. One of the questions often asked by Haskell newcomers is "how do I turn an IO a into an a?". The correct answer is that you don't; instead, you use a function (a -> m b) to indicate what you would have done with that a, and the bind operator takes care of the messy details for you. Stuart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On 8/2/07, Dougal Stanton <[EMAIL PROTECTED]> wrote: > Do I have an suggestions? Well, maybe the right way would be to do as > we do with map and fold, etc: show the explicitly recursive example, > then generalise. So, show how we could we would thread state in > Haskell, or how we would do optional (Maybe-style) values, then > generalise, *slowly* coalescing the more similar monads first before > reaching the 'top' of the monadic phylogenetic tree. > > Hmm, I can see that previous paragraph is not as clear as it could be. > But anyway: has anyone used this approach before? These immediately came to mind: "You Could Have Invented Monads! (And Maybe You Already Have.)" http://sigfpe.blogspot.com/2006/08/you-could-have-invented-monads-and.html [http://tinyurl.com/ecqzl] "Monads for Functional Programming" http://citeseer.ist.psu.edu/wadler95monads.html [http://tinyurl.com/2foj46] I personally received my first monadic enlightenment from Bird's "Introduction to Functional Programming using Haskell", which also uses the same approach. I think it's an excellent way to approach the topic. Stuart Cook ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
Seth Gordon wrote: > > Functors are a generalization from lists to "things that can be mapped > over" in general, and then monads are a generalization of functors. > Way to go! That way lies true co/monadic enlightenment. Put another way, monads are no more about (only) IO/sequencing than fmap is about (only) lists. To learn about monadic imperative programming there are excellent places for doing so, but to learn about co/monads qua co/monads well, too bad. So here's my co/monad tutorial, or at least the barest outline of one. I guess that almost everyone can "get" fmap :: (a -> b) -> (m a -> m b) if only they got a good workout at it. So let's do lists, then trees, then your favorite exponential types, say parsers. Howsoever it's done, be sure to get a good grip on fmap. Next introduce flip (>>=) :: (a -> m b) -> (m a -> m b) as a left-sided fmap. Thinking what it means to lift just one side "nicely" should motivate the return function and monadic laws. Here "nicely" is in the sense that fmap lifts "nicely." Of course the classy way of figuring out one-sided fmap's is to contemplate both flip (>>=) and (comonadic) coextension :: (m a -> b) -> (m a -> m b) at the same time. This is my preferred approach to a co/monad tutorial. For sure, You Could Have Invented Co/Monads Too. Seth Gordon wrote: > > Haskell solves the "how can I do I/O in a pure functional language" > problem by *turning the world inside-out*. Instead of taking data from > the mutable outside world, using functions to manipulate it, and > depositing results back into that world, you put your functions into the > IO monad. > But (the illusion of) taking data out from the real world, manipulating it, and then putting it back is exactly what the monadic-do syntax sugar accomplishes: do x <- inputFromRealWorld let y = manipulateIt x return y You could use (fmap manipulateIt) to "put" it into the IO monad as you describe, but monadic-do is by far the more common approach. -- View this message in context: http://www.nabble.com/Monad-Description-For-Imperative-Programmer-tf4198417.html#a12055086 Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
Kim-Ee Yeoh wrote: Seth Gordon wrote: Functors are a generalization from lists to "things that can be mapped over" in general, and then monads are a generalization of functors. Way to go! That way lies true co/monadic enlightenment. I feel like I still don't understand comonads. Maybe I just need a Zen comaster to hit me with a costick and then I'll become coenlightened. Haskell solves the "how can I do I/O in a pure functional language" problem by *turning the world inside-out*. Instead of taking data from the mutable outside world, using functions to manipulate it, and depositing results back into that world, you put your functions into the IO monad. But (the illusion of) taking data out from the real world, manipulating it, and then putting it back is exactly what the monadic-do syntax sugar accomplishes: The type system turns the world inside-out and then the do-notation provides a right-side-in syntax to code functions in the inside-out world. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Monad Description For Imperative Programmer
On Thursday 09 August 2007 04:02, Seth Gordon wrote: > I feel like I still don't understand comonads. If you haven't done so already, you might like to check out: "(Co)Monads for Grad Students" http://www.cas.mcmaster.ca/~carette/CAS706/F2006/presentations/comonads.pdf "Codata and Comonads in Haskell" http://www.cse.ogi.edu/PacSoft/publications/phaseiiiq10papers/codata.pdf Aelxis. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
Kaveh> "A monad is like a loop that can run a new function against its variable in each iteration." I’m an imperative programmer learning Haskell, so I’m a newbie, but I’ll give it a try ☺ Making mistakes is the best way to learn it ;) There are lots of different kinds of monads, but let’s stick to the IO monad first, which you seem to refer to. No *an IO monad is not a loop at all*. Instead, from an imperative programmer’s point of view, the following might be better: “an IO monad is a delayed action that will be executed as soon as that action is needed for further evaluation of the program.” The simple program main = getLine >>= putStrLn can be visually represented as (see attachment) The “world” (=a representation of your computer’s hardware) is passed to the main function, which passes it to all actions that it encounters during its lazy evaluation, causing the executing of the actions as an effect. The red wire through which the “world flows” is a “single thread”, it cannot be split (because the physical world cannot be copied!!!), so no unwanted side effects can ever occur, making IO safe in Haskell. When you write your IO program, this world object is never available (the IO type is a special internal type), so the red wire is erased from the diagram, and the getLine and putStrLn boxes become “delayed actions”. Imperative programmers like myself might initially be confused when they see Haskell’s do notation, because it looks like the actions are strict statements as in C/C++/Pascal/Java/C#/etc, but they are not. For example, try the following program: main = do last [ putStrLn "NOT executed although it is first in the list, as it is not used by the main function!", putStrLn "This action IS executed because it is evaluated by the main function." ] This is of course all due to Haskell’s laziness which only evaluates just those expressions that it needs to evaluate the main function. One thing to note in the diagram above is that the getLine box has TWO outputs, the String and the World. But functions can only have a single output, but this can be tuple. Hence the passing of the world from one box to the other is a bit more complicated. It is this pattern of extracting both values from the output and passing them to the next function and other related combinations that form the generic monad class, which can be used for many more things than IO. See http://haskell.org/haskellwiki/IO_inside for a much deeper and more correct explanation ☺ And for the pros here, did this newbie make any sense? Probably not ;-) Oh no, yet another monad explanation!!! Now the universe will most certainly collapse… No virus found in this outgoing message. Checked by AVG Free Edition. Version: 7.5.476 / Virus Database: 269.11.0/929 - Release Date: 31/07/2007 17:26 <>___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: RE [Haskell-cafe] Monad Description For Imperative Programmer
Kaveh> "A monad is like a loop that can run a new function against its variable in each iteration." I’m an imperative programmer learning Haskell, so I’m a newbie, but I’ll give it a try ☺ Making mistakes is the best way to learn it ;) I was a newbie not so long ago so I can understand the trouble of imperative programmers when they meet monads for the first time. I think the problem is due to a few bad tutorial still available on the web and which are making two mistakes: 1 - Focusing on the IO monad which is very special ; 2 - Detailing the implementation. As a newie we don't care and we would prefer to see how to use monads rather than how to develop monads. When you look at monads you see they can be used for controlling the evaluation order (list monad, error monad, IO monad). They can be used for side effects (IO, state monad). They can be seen as containers (list, Maybe). They can be used to provide a protected environment (tainting). So, it is difficult to see what they have in common. Of course, what they have in common is a set of algebraic laws : the monadic laws but it does not help to know it. I think that a way to see monads (and a consequence of the monadic laws) is that monads are interpreters for domain specific languages. Each monad will generally come with a runMonad function (runReader, runWriter etc...) to execute the monadic program. IO is different because runIO is controlled by the runtime and cannot be manipulated by the user. The monadic combinators >>= are used to build programs. It is a way to concatenate two small programs to create a bigger one. In fact a combinator like >>= is doing two things : building new sentences of your domain specific language and evaluating them. if you take the list monad as example : [1,2,3] >>= \x -> [x*2,x*3]. First a new sentence will be created : [[2,3],[4,6],[6,9]]. Then, it is evaluated to give [2,3,4,6,6,9]. Here the interesting part is the sentence construction one. In other monads it may be the evaluation one. So, instead of building a big sentence and then evaluating it, a monad is a dynamical interpreter. The sentences are built and evaluated progressively. But of course, as I said, I was a newbie not long ago so the experts will correct me if needed. Now, a bit of self promotion but just because it may help. I have summarized the problems I faced when I was a newbie learning Haskell : http://www.alpheccar.org/en/posts/show/67 Some people told me it was useful. It is a summary of how imperative programmers should change their state of mind to understand the Haskell way. alpheccar. There are lots of different kinds of monads, but let’s stick to the IO monad first, which you seem to refer to. No *an IO monad is not a loop at all*. Instead, from an imperative programmer’s point of view, the following might be better: “an IO monad is a delayed action that will be executed as soon as that action is needed for further evaluation of the program.” The simple program main = getLine >>= putStrLn can be visually represented as (see attachment) The “world” (=a representation of your computer’s hardware) is passed to the main function, which passes it to all actions that it encounters during its lazy evaluation, causing the executing of the actions as an effect. The red wire through which the “world flows” is a “single thread”, it cannot be split (because the physical world cannot be copied!!!), so no unwanted side effects can ever occur, making IO safe in Haskell. When you write your IO program, this world object is never available (the IO type is a special internal type), so the red wire is erased from the diagram, and the getLine and putStrLn boxes become “delayed actions”. Imperative programmers like myself might initially be confused when they see Haskell’s do notation, because it looks like the actions are strict statements as in C/C++/Pascal/Java/C#/etc, but they are not. For example, try the following program: main = do last [ putStrLn "NOT executed although it is first in the list, as it is not used by the main function!", putStrLn "This action IS executed because it is evaluated by the main function." ] This is of course all due to Haskell’s laziness which only evaluates just those expressions that it needs to evaluate the main function. One thing to note in the diagram above is that the getLine box has TWO outputs, the String and the World. But functions can only have a single output, but this can be tuple. Hence the passing of the world from one box to the other is a bit more complicated. It is this pattern of extracting both values from the output and passing them to the next function and other related combinations that form the generic monad class, which can be used for many more things than IO. See http://haskell.org/haskellwiki/IO_inside for a much deep
Re: RE [Haskell-cafe] Monad Description For Imperative Programmer
On 2 Aug 2007, at 5:13 am, alpheccar wrote: I think the problem is due to a few bad tutorial still available on the web and which are making two mistakes: 1 - Focusing on the IO monad which is very special ; 2 - Detailing the implementation. As a newie we don't care and we would prefer to see how to use monads rather than how to develop monads. When you look at monads you see they can be used for controlling the evaluation order (list monad, error monad, IO monad). They can be used for side effects (IO, state monad). They can be seen as containers (list, Maybe). They can be used to provide a protected environment (tainting). So, it is difficult to see what they have in common. Of course, what they have in common is a set of algebraic laws : the monadic laws but it does not help to know it. I think that a way to see monads (and a consequence of the monadic laws) is that monads are interpreters for domain specific languages. And so on. But please, let's keep one foot in the real world if possible. Monads were invented to solve the "how do I do imperative programming in a pure functional language" problem. We teach schoolchildren how to add. They spend years counting and adding before we point out that x+y == y+x. Most people leave high school without EVER having to know that the whole numbers are a ring or what that means. When they DO learn that, the only way they can really make sense of it is to turn it back to front "a ring is a collection of things and operations that is rather like whole numbers". In order to get almost anything *done* in a Haskell program, you HAVE to learn about the IO monad. You can get an amazing amount of useful stuff done without EVER learning about any other monad at all. The IO monad gets in your face all the time. You teach the IO monad before anything else about monads because if you *don't* teach about that, if you delay it any longer than you have to, the students become convinced that you can't do anything useful in Haskell and lose interest in learning anything else about it. Focussing on the implementation? Well, I believe in giving my students the original papers. One of them is "How to Declare an Imperative". Telling the students about the implementation is *important* to *gain their trust*. There's magic in Haskell, but THIS isn't magic. I go over it again and again: ">>= acts like semicolon; it's all about sequencing." If you've read the Science of Discworld books you will be familiar with the phrase 'lies-to-children'. You DON'T tell them the full truth, because it would take a long time, confuse the marrow out of their bones, and leave them feeling this was masturbatory mathematics, not real programming, having no connection with real world interests. Once they are reasonably comfortable with the IO monad, you can introduce ST. Once they are reasonably comfortable with the use of ST for arrays, you can show them the axioms that are required for monads to work the way we expect. Once they have got *that*, you can then show them that Maybe is a monad in that we can define the operations in a useful way that also satisfies the axioms. Then we can go onto other monads, except that in a first course, there isn't time for that. But at least we haven't scared them off completely by telling them that monads are interpreters. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: RE [Haskell-cafe] Monad Description For Imperative Programmer
Ok, I am guessing that if you were Neo in The Matrix, you would have taken the Blue Pill. Blue Pill people ask How. I suspect most people attracted to Haskell have already taken the Red Pill. Red Pill people ask Why. It is compulsion, not self-interest, that drives Red Pill people to look under the hood of their programming language. If you are a Blue Pill person, you will never understand. If you were a Red Pill person, you would never have written the following paragraph. ok wrote: If you've read the Science of Discworld books you will be familiar with the phrase 'lies-to-children'. You DON'T tell them the full truth, because it would take a long time, confuse the marrow out of their bones, and leave them feeling this was masturbatory mathematics, not real programming, having no connection with real world interests. Your students can choose for themselves whether to take the Blue Pill or Red Pill. The least you can do is offer them the choice. Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
On 8/1/07, Andrew Wagner <[EMAIL PROTECTED]> wrote: > For me, I think the key to monads is to really > understand 2 things about them: > ... > 2.) Monads are about sequencing Now I disagree on 2. Monads are no more about sequencing than binary operators are about sequencing. Sure, if you want to, you can define an operator like (*) to be non-commutative, so that a*b is different to b*a, but that doesn't really get to the essence of what a binary operator is. And in everyday usage we use (*) to mean ordinary commutative multiplication where there is no sense of sequencing. The same holds for monads. If you want to use them for sequencing the option is there, but there are plenty of commutative monads out there, for which the order of operations doesn't matter, and the fact that they are commutative doesn't make them any less monads. So while you can use monads to sequence, I don't think sequencing gets to the essence of what monads are. I suspect I hold a minority view here... :-) -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
> > "an IO monad is a delayed action that will be executed as soon as that action > is needed for further evaluation of the program." > I'm not sure I like this, as it seems to confuse the issue. An expert should correct me if I'm wrong, but monads in and of themselves don't depend on laziness. Rather, *everything* in haskell is lazy, unless explicitly strict-ified. As for the rest of your email, I don't necessarily disagree, but don't find it particularly helpful either. Which may, of course, be a personal thing. For me, I think the key to monads is to really understand 2 things about them: 1.) They are simply type constructor classes 2.) Monads are about sequencing For point 2, think about the two main things you have to define to create an instance of a monad: (>>=) :: m a -> (a -> m b) -> m b That is, you have two monadic actions, m a and m b, and bind says how to take the result of the first and fit it into the second -- in sequence! (>>) :: m a -> m b -> m b Again, we have 2 monadic actions that we're composing, in sequence. This time, we're just discarding the result of the first. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
Hello, > On 8/1/07, Andrew Wagner <[EMAIL PROTECTED]> wrote: > > For me, I think the key to monads is to really > > understand 2 things about them: > > ... > > 2.) Monads are about sequencing > > Now I disagree on 2. > > Monads are no more about sequencing than binary operators are about > sequencing. Sure, if you want to, you can define an operator like (*) > to be non-commutative, so that a*b is different to b*a, but that > doesn't really get to the essence of what a binary operator is. And in > everyday usage we use (*) to mean ordinary commutative multiplication > where there is no sense of sequencing. > > The same holds for monads. If you want to use them for sequencing the > option is there, but there are plenty of commutative monads out there, > for which the order of operations doesn't matter, and the fact that > they are commutative doesn't make them any less monads. So while you > can use monads to sequence, I don't think sequencing gets to the > essence of what monads are. > > I suspect I hold a minority view here... :-) > You are entirely correct. Data dependencies enforce/specify sequencing. -Jeff --- This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
Here's my rant about the way monads are explained in Haskell tutorials (which are much too polluted with nuclear waste to be safely approached): It is a big mistake to start with the IO monad. It pollutes and misdirects the understanding of what a monad is. The dreaded "nuclear waste" metaphor is actually a red herring, having nothing do do with a monad at all, merely the artifact of the absence of an exit function in the IO monad (which actually does exist and is called unsafePerformIO, but that is a secret. Shhh...), combined with Haskell's refusal to work for free. Monads are required to have an extrance (reification/constructor function) called return. They are *not* required to have an exit (reflection/deconstructor function). They *do* combine (bind) together like links in a chain, which is not a list but an equivalence class of trees, where the only thing that matters is the order of the leaves, so unlike a list you don't have to start at the tail and assemble one-by-one. [Actually, the compiler picks just one of these trees (the singly-linked list) but expects that all trees would evaluate the same.] They *do* bind only with flavors of themselves (State a cannot bind to IO b, though a monad transformer can merge the two). The output type of one monad instance must match the input type of another monad reification function (e.g. return) that it wants to bind to. In compensation for this tribalism, those snobby monads that want to clique off are out of luck: a monad cannot restrict what possible types can be used to construct a monad instance. That would be discrimination, and you must agree to accept all comers. Simple, no? Apparently not... Other things have nothing to do with monads per se gunk up the descriptions about monads: One red herring (the nuclear waste metaphor) refers to the fact since monads may or may not have an escape-clause (called variously runXXX, evalXXX, unsafePerformXXX), and IO in particular does not. The presence or absence of this has *nothing* to do with monads (only with IO), participates in no monadic laws, and shouldn't even be in the chapter on Monads. Whether nuclear waste seeps in (as in a State monad) or stays out (IO monad) has nothing to do with their monadic property and is a special property of those particular classes. Another even redder herring is the dreaded sequencing aspect. Monads do sequence *denotationally*, the way any nested closures sequence, which is exactly *backwards* from the naive understanding of sequencing: symbols defined to the left are in the *inner* scope, those to the right are in the *outer* scope. Perversely, when the symbols are evaluated, the rightmost monad is evaluated first. The leftmost monad in the program, the IO () passed in by main, is the *last* thing to be evaluated, not the first. The outermost monad (rightmost bound function) is in the driver seat, and is absolutely free to ignore the monad to its left (which in turn encloses monads to its left)! This includes of course the main input IO () monad. Don't believe me? Prelude> const 3 (return "Nuclear waste leaking..." >>= print) + 5 8 Phew, no nuclear waste leaked after all. What a relief! This sequencing then has nothing to do with *operational* sequencing. When the symbols are evaluated is the basic call-by-need data-dependent stuff of most Haskell symbols and again, has nothing to do with monads. I learned about the IO monad first and I regret it bitterly. It cost me a years' worth of misunderstanding. I misapprehended that a monad had something to do with nuclear waste and never escaping the single-threadedness. I hope the new O'Reilly book doesn't make that mistake. Teach IO right away, but just don't call it a monad. IO is the exception, not the rule, in the menagerie of Haskell monads. How does all this map to C++? A monad is a a class, with no useful interface for the end user, that looks roughly (i.e. I haven't tested it) like: template class Monad { public: virtual ~Monad() {} // return Monad(T t) : t_(t) {} // bind operator (>>=), where // F :: Monad -> (T -> Monad) -> Monad virtual template Monad operator>>(typename U::F f) = 0; private: T t_; }; C++ programmers will immediately see past the syntactic kruft to notice that 1) the constructor arg is not a value but an unevaluated function object, that starts out unevaluated. 2) The result of m >> f is a monad object, totally unevaluated. 3) There is no member function to do anything with the monad at all! As is, it is useless. Derivers of this class will naturally want to add such functionality: template class MyMonad : public Monad { // The parent class needs to know what type of monad // this can bind to typedef someUnaryFunctionObjectTypeReturningB F; // There is no input, just an output! // The input is via the constructor arg of the innermost monad B operator()() { ... start the ball rolling
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
On 8/1/07, Dan Weston <[EMAIL PROTECTED]> wrote: > The moral of the story is that monads are less than meets the eye. You > can create them and concatenate them I mostly sympathise with your rant, but I think you need to be clearer about what exactly is concatenated. In general you can't concatenate Monads. What you *can* concatenate are Kleisli arrows (ie. things of type Monad m => a -> m b). You can also apply Kleisli arrows to Monads, and that's what >>= does. I feel that talking about Monads without Kleisli arrows is like talking about category theory without arrows, or at least sets without functions. In each case, without the latter, the former is more or less useless. Also, I'm having a terminological difficulty that maybe someone can help with: 'Monad' is a type class. So what's 'IO'? Is the correct terminology 'instance' as in 'IO is an instance of Monad'. I consider 'IO' to be 'a monad' as that fits with mathematical terminology. But what about an actual object of type 'IO Int', say? Some people have been loosely calling such an object 'a monad'. That doesn't seem quite right. Maybe it's 'an instance of IO Int', though that's stretching the word 'instance' to meaning two different things. And if an object of type IO Int is in instance of IO Int, is it reasonable to also call it an 'instance of IO', or even 'an instance of Monad'? I'm sure there are proper words for all these things if someone fills me in. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
> The outermost monad (rightmost bound function) is in the driver seat, and is absolutely free to ignore the monad to its > left (which in turn encloses monads to its left)! This includes of > course the main input IO () monad. Don't believe me? > > Prelude> const 3 (return "Nuclear waste leaking..." >>= print) + 5 > 8 > > Phew, no nuclear waste leaked after all. What a relief! No, I don't believe you. It's true that the right monad instance can ignore its left sibling (same monad of course, just a different instance) to allow backtracking (the Const monad being a trivial example of this), but IO is not such a monad. Your example just shows that monad instance expressions (like any Haskell expression) are evaluated lazily in Haskell. I am relieved though, that no nuclear waste was leaked by your example. Dan Weston wrote: Here's my rant about the way monads are explained in Haskell tutorials (which are much too polluted with nuclear waste to be safely approached): It is a big mistake to start with the IO monad. It pollutes and misdirects the understanding of what a monad is. The dreaded "nuclear waste" metaphor is actually a red herring, having nothing do do with a monad at all, merely the artifact of the absence of an exit function in the IO monad (which actually does exist and is called unsafePerformIO, but that is a secret. Shhh...), combined with Haskell's refusal to work for free. Monads are required to have an extrance (reification/constructor function) called return. They are *not* required to have an exit (reflection/deconstructor function). They *do* combine (bind) together like links in a chain, which is not a list but an equivalence class of trees, where the only thing that matters is the order of the leaves, so unlike a list you don't have to start at the tail and assemble one-by-one. [Actually, the compiler picks just one of these trees (the singly-linked list) but expects that all trees would evaluate the same.] They *do* bind only with flavors of themselves (State a cannot bind to IO b, though a monad transformer can merge the two). The output type of one monad instance must match the input type of another monad reification function (e.g. return) that it wants to bind to. In compensation for this tribalism, those snobby monads that want to clique off are out of luck: a monad cannot restrict what possible types can be used to construct a monad instance. That would be discrimination, and you must agree to accept all comers. Simple, no? Apparently not... Other things have nothing to do with monads per se gunk up the descriptions about monads: One red herring (the nuclear waste metaphor) refers to the fact since monads may or may not have an escape-clause (called variously runXXX, evalXXX, unsafePerformXXX), and IO in particular does not. The presence or absence of this has *nothing* to do with monads (only with IO), participates in no monadic laws, and shouldn't even be in the chapter on Monads. Whether nuclear waste seeps in (as in a State monad) or stays out (IO monad) has nothing to do with their monadic property and is a special property of those particular classes. Another even redder herring is the dreaded sequencing aspect. Monads do sequence *denotationally*, the way any nested closures sequence, which is exactly *backwards* from the naive understanding of sequencing: symbols defined to the left are in the *inner* scope, those to the right are in the *outer* scope. Perversely, when the symbols are evaluated, the rightmost monad is evaluated first. The leftmost monad in the program, the IO () passed in by main, is the *last* thing to be evaluated, not the first. The outermost monad (rightmost bound function) is in the driver seat, and is absolutely free to ignore the monad to its left (which in turn encloses monads to its left)! This includes of course the main input IO () monad. Don't believe me? Prelude> const 3 (return "Nuclear waste leaking..." >>= print) + 5 8 Phew, no nuclear waste leaked after all. What a relief! This sequencing then has nothing to do with *operational* sequencing. When the symbols are evaluated is the basic call-by-need data-dependent stuff of most Haskell symbols and again, has nothing to do with monads. I learned about the IO monad first and I regret it bitterly. It cost me a years' worth of misunderstanding. I misapprehended that a monad had something to do with nuclear waste and never escaping the single-threadedness. I hope the new O'Reilly book doesn't make that mistake. Teach IO right away, but just don't call it a monad. IO is the exception, not the rule, in the menagerie of Haskell monads. How does all this map to C++? A monad is a a class, with no useful interface for the end user, that looks roughly (i.e. I haven't tested it) like: template class Monad { public: virtual ~Monad() {} // return Monad(T t) : t_(t) {} // bind operator (>>=), where // F ::
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
Hello, > 'Monad' is a type class. > > So what's 'IO'? Is the correct terminology 'instance' as in 'IO is an > instance of Monad'. I consider 'IO' to be 'a monad' as that fits with > mathematical terminology. > I agree with this. >But what about an actual object of type 'IO > Int', say? > I usually describe the type resulting from applying a monad a computation. Then 'IO Int' would be something like an IO computation of an Int. This terminology also jibes well with, or rather comes from, Moggi's computational lambda calculus (one of the early papers showing uses of Monads to computer science). -Jeff --- This e-mail may contain confidential and/or privileged information. If you are not the intended recipient (or have received this e-mail in error) please notify the sender immediately and destroy this e-mail. Any unauthorized copying, disclosure or distribution of the material in this e-mail is strictly forbidden.___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
a Monad is a type constructor with two operations, implementing a standard interface and following a few simple rules. the Monad type class tells you the interface (what operations you've got, and their types), the Monad laws tell you what all types implementing that interface should have in common. the monadic interface gives you two operations, one to throw things into a monad thing (return), and one to chain two monad things together (>>=). the chaining explicitly caters for information flowing from the first to the second parameter of (>>=). the monad laws tell you two useful facts about monad things thrown together in that way: whatever it is the monad does, anything just thrown into it will take no part in that action, and whichever way you use that chaining operation, the structure of chaining is irrelevant, only the ordering of chained monad things matters. there are usually other ways to create 'primitive' monadic things, which can be combined into complex monadic structures using the operations from the Monad interface. there is usually a way to interpret monadic structures built in this way (a 'run' operation of some kind). that's it, i think?-) claus examples include: - i/o: primitive monadic things are basic i/o operations, the 'run' operation is outside the language, applied to 'Main.main', and interprets (abstract) IO monad structures sequentially, starting with the leftmost innermost i/o operation in the structure and applying the second argument of (>>=) to the result of executing the first. - []: primitive monadic things are lists, the 'run' operation is the identity, ie, the lists are directly exposed as data structures, return creates a singleton list, (>>=) applies its second argument to each element of its first argument and concatenates the results (concatMap). - State: primitive monadic things are operations on a state type, returning a result and a state; return returns its parameter, passing its input state unchanged, (>>=) applies its first parameter to the input state, applies its second parameter to the result value and result state of the first. 'run' is runState and applies a (possibly) complex monadic thing to an input state, returning a result and a (modified) state. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
I knew someone was going to catch me wandering into the deep end of the pool! Having read large parts of your blog, I would never presume to tell you anything about Haskell or category theory, but what the hell... > I mostly sympathise with your rant, but I think you need to be clearer > about what exactly is concatenated. In general you can't concatenate > Monads. What you *can* concatenate are Kleisli arrows (ie. things of > type Monad m => a -> m b). You can also apply Kleisli arrows to > Monads, and that's what >>= does. > > I feel that talking about Monads without Kleisli arrows is like > talking about category theory without arrows, or at least sets without > functions. In each case, without the latter, the former is more or > less useless. OK, I'll be clearer. I did actually mean Kleisli arrows, though I disagree about your statement about concatenating monad instances and claims of "useless": Prelude> print "Hello" >> return 3 "Hello" 3 Granted, >> is not as "general" as >>=, so combining one monad instance with another is not as "general" as with a Kleisli arrow: concatenating degenerates to simple sequencing. Sequencing print statements is more rather than less useless to many people, but I see your point. Actually, you have made my point! :) The forgetful action of Kleisli arrows acting on a monad (or conversely the free algebra of a monad as a subspace of Kleisli arrows) is to my understanding intimately connected with the specialness of the IO monad. It is the continuous nature of Haskell monads that gives non-IO monads value. So I guess my rant really was about Kleisli arrows not all being forgetful functors, used only for their sequencing effect. It just sounded too hard to pull that argument off without reinforcing the myth that you need to know category theory to have a rant about Haskell tutorials. > Also, I'm having a terminological difficulty that maybe someone can help with: > > 'Monad' is a type class. Actually I thought it was a type class constructor. The monad Monad m => m a is continuous in its instance type a, which is important in establishing the relationship between >>= and >>. The Haskell type 'IO ()' is a monad instance that is also isomorphic to the discrete trivial monad, but that is not a Haskell Monad capital-M. I used the term "instance" because the type IO () is an instance of the typeclass IO, not for any more profound reason. Forgive the display of wanton ignorance above. After all, isn't that what ranting is all about? Dan Weston Dan Piponi wrote: On 8/1/07, Dan Weston <[EMAIL PROTECTED]> wrote: The moral of the story is that monads are less than meets the eye. You can create them and concatenate them I mostly sympathise with your rant, but I think you need to be clearer about what exactly is concatenated. In general you can't concatenate Monads. What you *can* concatenate are Kleisli arrows (ie. things of type Monad m => a -> m b). You can also apply Kleisli arrows to Monads, and that's what >>= does. I feel that talking about Monads without Kleisli arrows is like talking about category theory without arrows, or at least sets without functions. In each case, without the latter, the former is more or less useless. Also, I'm having a terminological difficulty that maybe someone can help with: 'Monad' is a type class. So what's 'IO'? Is the correct terminology 'instance' as in 'IO is an instance of Monad'. I consider 'IO' to be 'a monad' as that fits with mathematical terminology. But what about an actual object of type 'IO Int', say? Some people have been loosely calling such an object 'a monad'. That doesn't seem quite right. Maybe it's 'an instance of IO Int', though that's stretching the word 'instance' to meaning two different things. And if an object of type IO Int is in instance of IO Int, is it reasonable to also call it an 'instance of IO', or even 'an instance of Monad'? I'm sure there are proper words for all these things if someone fills me in. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
> From: [EMAIL PROTECTED] > [mailto:[EMAIL PROTECTED] On Behalf Of peterv > > However, one thing which I find annoying is that a "classic > pure" function cannot evaluate an IO function unless you use > unsafePerformIO; one must "promote" (?demote) the pure > function into the IO monad. That's just a property of the IO monad, rather than monads in general: http://www.haskell.org/all_about_monads/html/laws.html#nowayout > Any ways of "promoting" such a pure function into the monadic > one automatically? I tried playing with "liftM", without succes. This is where Claus plugs HaRe :-) (although liftM + friends is normally what one uses). You might find this relevant: http://www.cs.kent.ac.uk/projects/refactor-fp/catalogue/Monadification1. html Some people (but I'm not sure who) probably write most of their Haskell code in a monadic style, so as to make conversion between various monads less painful. It's still pure... Alistair * Confidentiality Note: The information contained in this message, and any attachments, may contain confidential and/or privileged material. It is intended solely for the person(s) or entity to which it is addressed. Any review, retransmission, dissemination, or taking of any action in reliance upon this information by persons or entities other than the intended recipient(s) is prohibited. If you received this in error, please contact the sender and delete the material from any computer. * ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
RE: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
IMHO although this is a great explanation of what a monad is (as far as I understand it), for newbies I think it helps a lot to first look at the specific cases where monads are used and why they are invented, as explained in http://sigfpe.blogspot.com/2006/08/you-could-have-invented-monads-and.html and then looking at http://haskell.org/haskellwiki/IO_inside for the IO thingy. However, one thing which I find annoying is that a "classic pure" function cannot evaluate an IO function unless you use unsafePerformIO; one must "promote" (?demote) the pure function into the IO monad. For example, as an exercise I tried to convert the Monte Carlo experiment as demonstrated in http://mitpress.mit.edu/sicp/full-text/sicp/book/node53.html into Haskell (warning: newbie code ahead, should be much nicer when I once become a real Haskeller in a million years ;-) In the code below I had to change the monteCarlo1 into a completely different monteCarlo2 in order to use the IO random facility. Okay, this is "expected behavior", but for an imperative programmer, this is quite a shock! Any ways of "promoting" such a pure function into the monadic one automatically? I tried playing with "liftM", without succes. import Data.Ratio import Data.List import System.Random import Control.Monad -- Monte Carlo using "pure" functions monteCarlo1 :: Integral n => n -> (a -> (a,Bool)) -> a -> Ratio n monteCarlo1 trials experiment startValue = trialsPassed % trials where trialsPassed = genericLength $ filter id outcomes outcomes = snd $ unzip $ genericTake trials $ iterate (experiment . fst) (experiment startValue) cesaroTest1 :: StdGen -> (StdGen, Bool) cesaroTest1 gen0 = (gen2, (gcd rand1 rand2) == 1) where (rand1, gen1) = random gen0 (rand2, gen2) = random gen1 estimatePi1 trials = sqrt $ 6 / (fromRational $ monteCarlo1 trials cesaroTest1 (mkStdGen 0)) -- Monte Carlo using monadic IO -- no genericReplicateM, so must use Int monteCarlo2 :: Int -> IO Bool -> IO (Ratio Integer) monteCarlo2 trials experiment = do outcomes <- replicateM trials experiment return $ fromIntegral (genericLength $ filter id outcomes) % fromIntegral trials cesaroTest2 = do rand1 <- getStdRandom random rand2 <- getStdRandom random return $ (gcd rand1 rand2) == 1 estimatePi2 trials = do mc <- monteCarlo2 trials cesaroTest2 return $ sqrt $ 6 / (fromRational mc) main = let pi1 = estimatePi1 5 in do pi2 <- estimatePi2 5 putStrLn (show pi1) >> putStrLn (show pi2) -Original Message- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Claus Reinke Sent: Thursday, August 02, 2007 12:18 AM To: haskell-cafe@haskell.org Subject: Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer a Monad is a type constructor with two operations, implementing a standard interface and following a few simple rules. the Monad type class tells you the interface (what operations you've got, and their types), the Monad laws tell you what all types implementing that interface should have in common. the monadic interface gives you two operations, one to throw things into a monad thing (return), and one to chain two monad things together (>>=). the chaining explicitly caters for information flowing from the first to the second parameter of (>>=). the monad laws tell you two useful facts about monad things thrown together in that way: whatever it is the monad does, anything just thrown into it will take no part in that action, and whichever way you use that chaining operation, the structure of chaining is irrelevant, only the ordering of chained monad things matters. there are usually other ways to create 'primitive' monadic things, which can be combined into complex monadic structures using the operations from the Monad interface. there is usually a way to interpret monadic structures built in this way (a 'run' operation of some kind). that's it, i think?-) claus examples include: - i/o: primitive monadic things are basic i/o operations, the 'run' operation is outside the language, applied to 'Main.main', and interprets (abstract) IO monad structures sequentially, starting with the leftmost innermost i/o operation in the structure and applying the second argument of (>>=) to the result of executing the first. - []: primitive monadic things are lists, the 'run' operation is the identity, ie, the lists are directly exposed as data structures, return creates a singleton list, (>>=) applies its second argument to each element of its first argument and concatenates the results (concatMap). - State: primitive monadic things are operations on a state
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
On 8/2/07, Dan Piponi <[EMAIL PROTECTED]> wrote: > I feel that talking about Monads without Kleisli arrows is like > talking about category theory without arrows, or at least sets without > functions. In each case, without the latter, the former is more or > less useless. The chapter on monads in Bird's "Introduction to Functional Programming using Haskell" introduces an operator (<>) that's equivalent to (>>>) on Kleisli arrows, without the intermediate newtype. One nice property of this operator is that it turns "return" into a genuine identity, rather than the weird pseudo-identity that it forms with (>>=). Sadly I don't actually own a copy of the book, so most of this is from memory. > Also, I'm having a terminological difficulty that maybe someone can help with: > > [snip][What's a good word for an object of type IO Int?] I tend to call it a "value in the [IO] monad". I don't claim to be a canonical reference, though. Stuart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: FW: RE [Haskell-cafe] Monad Description For Imperative Programmer
On 8/1/07, Jeff Polakow <[EMAIL PROTECTED]> wrote: > >But what about an actual object of type 'IO > > Int', say? > > > I usually describe the type resulting from applying a monad a computation. Same here. If "m" is a monad, then "m a" is a computation. (Of course, computations are first-class values, like functions.) I've occasionally called functions of type "a -> m b" monadic functions, but I suspect that's poor style. I wonder how much of the confusion surrounding monads comes from the fact that using them in Haskell involves higher-order functions, type constructors, and type constructor classes. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe