tag:blogger.com,1999:blog-11295132.post115499678320066610..comments2014-12-04T12:37:01.029-08:00Comments on A Neighborhood of Infinity: You Could Have Invented Monads! (And Maybe You Already Have.)Dan Piponihttps://plus.google.com/107913314994758123748noreply@blogger.comBlogger65125tag:blogger.com,1999:blog-11295132.post-88946777962005425272014-10-03T06:08:09.517-07:002014-10-03T06:08:09.517-07:00For the Writer Monad (first example of debug state...For the Writer Monad (first example of debug state); why would you not just solve the problem with a function of the following type:<br /><br />(Result, String) -> (Result, String)<br /><br />The second parameter in the tuple can carry your logging info from function call to the next.<br /><br />This appears simpler to a programmer without Monad experience.Sam Isaacsonhttp://www.blogger.com/profile/02856720364470192009noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-69888657783004054822014-03-26T02:11:07.035-07:002014-03-26T02:11:07.035-07:00This comment has been removed by the author.AngryGamerhttp://www.blogger.com/profile/03263062369175945973noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-87868172062614092262014-03-26T02:10:24.993-07:002014-03-26T02:10:24.993-07:00Confused with the sixth root example. You describe...Confused with the sixth root example. You describe<br />sixth root = sqrt( cubrt x) yet the diagram shows cubrt (sqrt x).AngryGamerhttp://www.blogger.com/profile/03263062369175945973noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-74880761889189815402013-11-14T07:14:49.815-08:002013-11-14T07:14:49.815-08:00Brilliant stuff. This has really helped me. Thanky...Brilliant stuff. This has really helped me. Thankyou !!!<br />This is a very useful tutorial which will never get outdated.<br />So please can the following be fixed for the sake and sanity of<br />future readers (of which I'm sure there will be many)...<br /><br />As DAY and and Pupeno have already said...<br /><br />The piece of code just before exercise two would be more understandable<br />if it said "unit * f' = f' * unit".<br /><br />The original says "unit * f = f * unit = f" which is simply not true if<br />f refers to the same f as mentioned previously in the article (which is what<br />the ready would naturally assume).<br /><br />This hurt my head for a couple of hours before I finally realised it<br />was a mistake (or ambiguous at best).<br /><br />Thanks,johnhttp://www.blogger.com/profile/03502200064229800787noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-72163982990115569502013-11-14T07:13:18.963-08:002013-11-14T07:13:18.963-08:00Brilliant stuff. This has really helped me. Thanky...Brilliant stuff. This has really helped me. Thankyou !!!<br />This is a very useful tutorial which will never get outdated.<br />So please can the following be fixed for the sake and sanity of<br />future readers (of which I'm sure there will be many)...<br /><br />As DAY and and Pupeno have already said...<br /><br />The piece of code just before exercise two would be more understandable if it said "unit * f' = f' * unit".<br /><br />The original says "unit * f = f * unit = f" which is simply not true if "f" refers to the same f as mentioned previously in the article (which is what<br />the ready would naturally assume).<br /><br />This hurt my head for a couple of hours before I finally realised it<br />was a mistake (or ambiguous if you prefer).<br /><br />Thanks,<br />Johnjohnhttp://www.blogger.com/profile/03502200064229800787noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-38257923299182240022013-03-03T04:11:22.548-08:002013-03-03T04:11:22.548-08:00Great Tutorial, thanks!
But I'm confused: In ...Great Tutorial, thanks!<br /><br />But I'm confused: In exercise 6 we are to prove that lift f * lift g = lift (f.g).<br /><br />But, by definition, f . g is not defined (in contrast to exercise 3).Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-45893260485278407402012-05-09T12:13:48.736-07:002012-05-09T12:13:48.736-07:00Great, great article !
it is the only one I have r...Great, great article !<br />it is the only one I have read (and I read some) that defines a monad by what it <i>is</i> rather than by what it <i>does</i>.<br />I had been very frustrated and confused by the what-it-does approach of explaining monads... I even had been wondering if Haskell was not a complicated way to do simple things...<br /><br />So thank you so much !Tanneguyhttp://www.blogger.com/profile/11749586993176681714noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-85173195393146403932012-03-22T12:59:52.010-07:002012-03-22T12:59:52.010-07:00I never comment on these things,
But thanks so muc...I never comment on these things,<br />But thanks so much.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-28009208982081155552012-02-11T05:59:02.631-08:002012-02-11T05:59:02.631-08:00The best tutorial on Monads! - Thank youThe best tutorial on Monads! - Thank youAnonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-63850939290750748192010-12-31T18:16:42.730-08:002010-12-31T18:16:42.730-08:00For not being a Haskell programmer, I've read ...For not being a Haskell programmer, I've read a fair number of explanations of monads over the past year (I blame Reddit). So far, I've hit two that have helped; an eight-word definition ("Monads provide a generalized interface to sequential computation."), and your exposition I just tripped across.<br /><br />You've managed to take something that is somewhat impenetrable when presented by others and make the concept not merely natural but truly inevitable once we reach a certain level of abstraction. I suspect this means you normally teach math.<br /><br />Anyway, thank you for this.Ray Leehttp://www.blogger.com/profile/00675537654195582090noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-48058064868307250442010-12-13T02:57:27.296-08:002010-12-13T02:57:27.296-08:00Thanks a lot for a great tutorial.
I've been...Thanks a lot for a great tutorial. <br /><br />I've been searching for a while and this is the best one I've found so far, both in books and on the net.Eternalhttp://www.blogger.com/profile/02512322446421154424noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-84086862229362019002010-11-17T15:40:04.427-08:002010-11-17T15:40:04.427-08:00This tutorial is a great introduction to monads as...This tutorial is a great introduction to monads as it starts with the problem and let the reader develop (or even invent) the solution. This helped me a lot, thanks!Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-89084821569886816612010-08-19T07:24:19.904-07:002010-08-19T07:24:19.904-07:00Anonymous,
The version I gave highlights a certai...Anonymous,<br /><br />The version I gave highlights a certain symmetry in the signature. It's of the form X -> F a -> F b. That's slightly hidden in your version. Of course they are equivalent, but it's this symmetry I want people to notice.sigfpehttp://www.blogger.com/profile/08096190433222340957noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-684848420849340442010-08-18T22:07:57.774-07:002010-08-18T22:07:57.774-07:00Is it an academic convention to write your type si...Is it an academic convention to write your type signatures like this?<br /><br />bind :: (a → StdGen → (b,StdGen)) → (StdGen → (a,StdGen)) → (StdGen → (b,StdGen))<br /><br />It would be much, much more clear if you wrote it like this:<br /><br />bind :: (a → StdGen → (b,StdGen)) → (StdGen → (a,StdGen)) → StdGen → (b,StdGen)<br /><br />Obviously the two are equivalent but it looks like you <i>intend</i> for the first one to return a function rather than accept a third argument.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-12074275314913628592010-07-02T05:47:46.971-07:002010-07-02T05:47:46.971-07:00An excellent tutorial. It really helped me a lot i...An excellent tutorial. It really helped me a lot in understanding monads. The key was the 'bind' function with the more natural order of parameters compared to '>>='. The '*' operator really made clear what is going on, and it was really simple to define it in terms of 'bind'. I also liked that you created exercises to force me stop and think, thus helping in the understanding of the concept.<br /><br />On the downside: the wording before the bind function of the random number example needs a little bit of improvement, exercise 7 was the most difficult because of it.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-66143417341071129732010-03-09T13:22:04.934-08:002010-03-09T13:22:04.934-08:00Bravo - what a great tutorial ! I've read abou...Bravo - what a great tutorial ! I've read about a dozen articles and not really understood Monads but this one really hits the nail. Thanks.Andrew Whaleyhttp://www.blogger.com/profile/05346078852977103014noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-16776721071397495472010-03-04T04:34:11.699-08:002010-03-04T04:34:11.699-08:00It would be better to change unit * f = f * unit =...It would be better to change unit * f = f * unit = f in the paragraph above Exercise Two into unit * f' = f' * unit = f'. And a space is missing in f'*g' in the same paragraph.DAYhttp://www.blogger.com/profile/14359320866411018319noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-55121518036084311422009-11-24T01:23:04.451-08:002009-11-24T01:23:04.451-08:00About the do notation, you basically said:
do {le...About the do notation, you basically said:<br /><br />do {let x = y; more code} ==>> (\x -> do more code) y<br /><br />I was confused at first, until I performed the obvious beta reduction:<br /><br />let x = y in do more code<br /><br />This is actually closer to the original do notation, closer to the other rules, and I think a bit clearer.<br /><br />Anyway, thank you. I now have a way to explain monads to my poor C++ colleagues.Loup Vaillanthttp://www.loup-vaillant.frnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-46175663180702319112009-08-06T04:35:31.952-07:002009-08-06T04:35:31.952-07:00Great post, really made monads easy to understand....Great post, really made monads easy to understand. <br /><br />Any chance you could write the same sort of thing on call/cc ?James Brookshttp://www.blogger.com/profile/16899320910026266930noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-53934320056879658552009-02-12T07:06:00.000-08:002009-02-12T07:06:00.000-08:00Nice tutorial, but I don't like "your fav...Nice tutorial, but I don't like "your favorite number" ;>Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-19765545956025950642008-07-14T02:37:00.000-07:002008-07-14T02:37:00.000-07:00In the line "Where we previously used a pair like ...In the line "Where we previously used a pair like (a,s) we now use Writer (a,s) of type Writer Char.", shouldn't it be type Writer [Char]?<BR/><BR/>Thanks.Anonymousnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-4027648802914084112008-06-05T16:34:00.000-07:002008-06-05T16:34:00.000-07:00About the randomized functions: All the confusion ...About the randomized functions: All the confusion is due to Curry-Howard iso making it unclear what is an argument and what is the return value. Depending on your view you get two different monad types. When you say "The first element of the pair that f returns" it seems clear that you view f as a 2-argument function which returns a pair and thus that the monad type should be (a, StdGen), but your solution of bind is the one for monad type StdGen -> (a, StdGen) which results from viewing f as a function of one argument which returns a function.<BR/>Your choice of names x and x' in your definition of bind is VERY confusing. Might I suggest instead: bind f r = \s -> let (x, s') = r s in f x s'? Other suggested rewording:<BR/>"We now must work out how to compose two randomized functions, f and g. The pair that the function that is returned by g returns needs to be decomposed and passed in as input to f. So we can give this signature for bind:".<BR/>It would also be very good if you could explain what happens if you choose the monad type to be (a, StdGen) and why that is a bad idea (if it is).<BR/>Lastly, I do think you offer a very enlightening view of monads, so thank you.Marijn Schoutennoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-84398040521807520822008-02-01T17:44:00.000-08:002008-02-01T17:44:00.000-08:00knut,The function you defined is called "compositi...knut,<BR/><BR/>The function you defined is called "composition of Kleisli arrows". I wrote a bit about it here: http://sigfpe.blogspot.com/2006/06/monads-kleisli-arrows-comonads-and.htmlsigfpehttp://www.blogger.com/profile/08096190433222340957noreply@blogger.comtag:blogger.com,1999:blog-11295132.post-22197339697557299352008-02-01T17:31:00.000-08:002008-02-01T17:31:00.000-08:00Great tutorial! I especially liked the comparison ...Great tutorial! I especially liked the comparison between binding and function composition. In fact, for your examples, I find the "f*g" notation more succinct than both using >>= directly and the do notation. So far I haven't found an equivalent operator in Haskell, so for now I'm using the following:<BR/><BR/><B><BR/>module MonadUtils where<BR/>(°) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c)<BR/>f ° g = (>>= f) . g<BR/></B><BR/><BR/>While probably not suitable for IO, it's a pretty neat way of writing stuff like<BR/><BR/><B><BR/>sixthrt' = sqrt' ° cbrt'<BR/>(x',w) = runWriter $ (f ° g ° h) x<BR/></B>knutnoreply@blogger.comtag:blogger.com,1999:blog-11295132.post-72431564045982593142008-01-08T08:49:00.000-08:002008-01-08T08:49:00.000-08:00Andrew,Sorry that caused confusion. Just treat the...Andrew,<BR/><BR/>Sorry that caused confusion. Just treat the two symbols the same way. At that point I was still trying to figure out which symbol was better to use and hadn't settled for one or the other. If I get time I'll try to make it consistent.sigfpehttp://www.blogger.com/profile/08096190433222340957noreply@blogger.com