Re: [Haskell-cafe] Is my code too complicated?
On 5 July 2010 10:39, Yves Parès wrote: > Then what is your alternative? How do you replace monad transformers? Possibly more a case of doing without rather than replacing them with something else, you would amalgamate all the monadic effects you want into one monad. E.g. State and Environment (reader) and partiality (Maybe) newtype Amalgamated s e a = Amalgamated { getAmalgamated :: e -> s -> (Maybe a,st) } instance Monad (Amalgamated s e) where return a = Amalgamated $ \e s -> return (Just a, st) m >>= k = Amalgamated $ \e s -- TODO (after the first coffee of the morning...) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
> > About monad transformers, I don't really like to use them because they > can get hairy in some cases, and because they have poor performance in > other cases. > Then what is your alternative? How do you replace monad transformers? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
On 3 July 2010 15:04, Andrew Coppin wrote: > > I said "does something that doesn't fall under one of these". The identity > monad, by contrast, does nothing that does fall under these. :-P (It falls > under zero of these.) Okay, how about: The probability monad The powerset monad The monad of locales http://www.cs.bham.ac.uk/~mhe/papers/pinjective.pdf The filter monad http://www.cs.bham.ac.uk/~mhe/papers/filtersnorthbay2.pdf Once you move into the mathematically territory I couldn't tell you want the monads actually do, but on the surface they don't seem very "effectful". ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
Stephen Tetley wrote: On 3 July 2010 14:20, Andrew Coppin wrote: Tangentally, it seems to me that all monads can be described as doing zero or more of: - Invisibly pass state around (and possibly modify it). - Perform unusual flow control. - I/O (or some restricted subset of it). Can anybody think of a monad that does something that doesn't fall under one of these categories? The Identity monad of course. You did ask... I said "does something that doesn't fall under one of these". The identity monad, by contrast, does nothing that does fall under these. :-P (It falls under zero of these.) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
Ivan Lazar Miljenovic wrote: Stephen Tetley writes: On 3 July 2010 14:20, Andrew Coppin wrote: Tangentally, it seems to me that all monads can be described as doing zero or more of: - Invisibly pass state around (and possibly modify it). - Perform unusual flow control. What do you consider "unusual"? Not the usual flow control that you'd implement by simply chaining vanilla functions together. Maybe and similar error monads implement early exit. List and similar containers implement multiple execution in some order or other. There are monads that implement choice. Cont implements... uh, everything? Even STM, which is largely about state mutation, implements [very] unusual flow control - the flow is controlled by other concurrent threads! ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
Most languages today provide a certain "glue" to bring everything together. Most languages today provide several kinds of glue and, while some of those kinds are not recommended, Haskell unfortunately doesn't provide all useful kinds of glue. Especially the module system is a weak point: in SML, you'd have parameterized modules, in Java, you'd have dependency injection (of course, being Java, they do everything the hard way, via XML and reflection; but they are already on their way back, with things like Spring, annotations, and aspect-oriented programming, pushing full reflection under the hood, permitting to compose plain-old Java objects, and reducing the role of XML configuration files), in Haskell, we have ?? (yes, extended type-classes are equivalent to SML modules in theory, but not in hackage practice, nor are first-class modules modelled via extensible records). The problem with that approach is: This makes my code harder to understand for beginners. Usually they can tell /what/ my code is doing, because it's written in natural language as much as possible, but they couldn't reproduce it. And when they try to learn it, they give up fast, because you need quite some background for that. What kind of beginner? What kind of background? Since you are talking to a PHP developer, you will first have to repeat the common parts of both languages, pointing out all the headaches that disappear when moving from PHP to even imperative Haskell (static scoping and IO typing means no accidental global variables or accidental side-effects, much less manual-reading to figure out which parts of some library API are functional, which have side-effects, etc.). Then your friend has to start trusting the compiler (those unit tests that only make sure that we don't break scoping disappear; those defensively programmed runtime type checks and comment annotations disappear in favour of real statically checked types; etc) and libraries (much less worrying about whether some library routine will modify its parameters in place; callbacks are no big deal or new feature; many design patterns can actually be encoded in libraries, rather than pre-processors; which means that small-scale design patterns are worth a library; etc.). Once that happens, a whole lot of thinking capacity is freed for worrying about higher-level details, and you two will have an easier time walking through high-level abstractions. Do not try to lead your friends through higher-order abstractions in Haskell when they are still worrying about small stuff like scoping or type safety - that would be frightening. Also sometimes when I write Haskell, my friend sits beside me and watches. When he asks (as a PHP programmer with some C background), say, about my types, I can't give a brief explanation like I could in other languages. When looking through job adverts, I get the impression that nobody is working in plain programming languages anymore: it is Java plus Spring plus persistence framework plus web framework plus .., and for PHP especially, it is some framework or content-management system that just happens to be programmed and extended in PHP, but otherwise has its own language conventions and configuration languages. If you think of monad transformers and the like as mini-frameworks, implemented *without* changing the language conventions, should they not be easier to explain than a PHP framework or preprocessor that comes with its own syntax/semantics? Yesterday I was writing a toy texture handler for OpenGL (for loading and selecting textures). He asked about my TextureT type. I couldn't explain it, because you couldn't even express such a thing in PHP or C. type TextureT = StateT Config -- Note that this is MonadLib. -- BaseM m IO corresponds to MonadIO m. selectTexture :: BaseM m IO => B.ByteString -> TextureT m () State monads are the ones that translate most directly to an OOP pattern from the Smalltalk days: method chaining (each method returns its object, so you can build chains of method calls just as you can chain monad operations. The state is held in the object (which is similar to holding a record in a State monad instead of nesting State transformers, but inheritance could be likened to nesting). Of course, in imperative OOP languages, only programmer discipline keeps you from modifying other objects as well, while in Haskell, the type system sets safety boundaries (not in the "there is something wonderful you can't do" sense but in the "you'd hurt someone if you'd do that" sense). I fear that my code is already too difficult to understand for beginners, and it's getting worse. But then I ask myself: I've got a powerful language, so why shouldn't I use that power? After all I haven't learnt Haskell to write C code with it. And a new Haskell programmer doesn't read my code to learn Haskell. They first learn Haskell and /then/ read my code. It is necessary to understand enough of Haskell that one get
Re: [Haskell-cafe] Is my code too complicated?
Stephen Tetley writes: > On 3 July 2010 14:20, Andrew Coppin wrote: > >> Tangentally, it seems to me that all monads can be described as doing zero >> or more of: >> - Invisibly pass state around (and possibly modify it). >> - Perform unusual flow control. What do you consider "unusual"? -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
On 3 July 2010 14:20, Andrew Coppin wrote: > Tangentally, it seems to me that all monads can be described as doing zero > or more of: > - Invisibly pass state around (and possibly modify it). > - Perform unusual flow control. > - I/O (or some restricted subset of it). > Can anybody think of a monad that does something that doesn't fall under one > of these categories? The Identity monad of course. You did ask... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
Felipe Lessa wrote: Oh, so it is about monad transformers. =) I agree that it gets harder to reason about the code. In fact, sometimes I stack monad transformers in the wrong order. About monad transformers, I don't really like to use them because they can get hairy in some cases, and because they have poor performance in other cases. Yet the decision of using transformers or not should be made depending on your particular needs. In my experience, using more than one monad transformer at once makes code utterly incomprehensible. (!) In my humble opinion, this is the principle weakness of monads; they allow you to do lots of cool stuff, but it's intractibly hard to mix several of them together. (See, for example, the combinatorial explosion of class instances in the MTL package.) On the few occasions I've attempted to use monad transformers, I've often wasted hours staring at a single function call, desperately trying to make it type-check. I almost which there was some kind of automated tool to tell you which magic combination of library functions generates an expression of the correct type. (But there isn't. Hoogle will tell you if any existing function vaguely matches what you want, but it's no help in suggesting how to combine a dozen functions together to get the right type.) Tangentally, it seems to me that all monads can be described as doing zero or more of: - Invisibly pass state around (and possibly modify it). - Perform unusual flow control. - I/O (or some restricted subset of it). Can anybody think of a monad that does something that doesn't fall under one of these categories? (For example, a parser monad carries around invisible state - the current source location, the input being parsed, etc. It also usually implements choice - in other words, unusual flow control. And some like Parsec allow you to do I/O as well.) type TextureT = StateT Config -- Note that this is MonadLib. -- BaseM m IO corresponds to MonadIO m. selectTexture :: BaseM m IO => B.ByteString -> TextureT m () "It is the type of functions that may access and modify a state of type Config." Damn, *I* didn't manage to figure that out, never mind PHP n00bs... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
On Sat, Jul 3, 2010 at 9:25 AM, Ertugrul Soeylemez wrote: > Haskell provides a lot of low level glue like laziness, currying and > other very helpful language features. But what is different in Haskell > is that it doesn't seem to provide any high level glue like other > languages do, especially when it comes to the IO world. There is a > somewhat powerful module system, but nothing to bring modules and the > objects they define together in a consistent way. When I first read this paragraph, I thought: "STM to the rescue!". STM is one of the best concurrent world glues, IMHO. > In my opinion this is both a disadvantage and an advantage. It's bad > because there is no standard way of gluing, nothing everybody learns and > uses. On the other hand it's good, because you can make your own glue. > This has proven very useful for me. My usual way is writing monad > transformers and sticking them together, often together with concurrent > programming. Oh, so it is about monad transformers. =) If you want, you may use Haskell just as you as PHP or C: just put everything in IO. Your code will get uglier and the type system won't catch many bugs, but that's what we get when doing C or PHP, right? > The problem with that approach is: This makes my code harder to > understand for beginners. Usually they can tell /what/ my code is > doing, because it's written in natural language as much as possible, but > they couldn't reproduce it. And when they try to learn it, they give up > fast, because you need quite some background for that. Also sometimes > when I write Haskell, my friend sits beside me and watches. When he > asks (as a PHP programmer with some C background), say, about my types, > I can't give a brief explanation like I could in other languages. I agree that it gets harder to reason about the code. In fact, sometimes I stack monad transformers in the wrong order. However, as Ivan says, if the feature is useful for you, don't be afraid of using it. Beginners may have a hard time grasping the concepts for the first time, but that's only until they "get it". About monad transformers, I don't really like to use them because they can get hairy in some cases, and because they have poor performance in other cases. Yet the decision of using transformers or not should be made depending on your particular needs. > Yesterday I was writing a toy texture handler for OpenGL (for loading > and selecting textures). He asked about my TextureT type. I couldn't > explain it, because you couldn't even express such a thing in PHP or C. > > type TextureT = StateT Config > > -- Note that this is MonadLib. > -- BaseM m IO corresponds to MonadIO m. > selectTexture :: BaseM m IO => B.ByteString -> TextureT m () "It is the type of functions that may access and modify a state of type Config." Cheers, -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
Hello Ertugrul, Saturday, July 3, 2010, 4:25:22 PM, you wrote: > This has proven very useful for me. My usual way is writing monad > transformers and sticking them together, often together with concurrent > programming. > ... /what/ my code is > doing, because it's written in natural language as much as possible can we see such code? i always thought that monad transformers are hard to use since you need to lift operations from inner monads on every use -- Best regards, Bulatmailto:bulat.zigans...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Is my code too complicated?
Ertugrul Soeylemez writes: [snip] > I fear that my code is already too difficult to understand for > beginners, and it's getting worse. But then I ask myself: I've got a > powerful language, so why shouldn't I use that power? After all I > haven't learnt Haskell to write C code with it. And a new Haskell > programmer doesn't read my code to learn Haskell. They first learn > Haskell and /then/ read my code. > > Is this a real problem or am I just exaggerating? > What do you think? I think that code should be written in as clear a manner as possible without affecting performance or functionality. That is, don't write the code complicated just for the sake of it, but don't be afraid to use extensions or advanced techniques if you think it's worth it. That said, whilst the problem might be more pronounced in Haskell, do all Java programmers instantly understand Factory patterns, etc.? This isn't a Haskell-specific pattern... -- Ivan Lazar Miljenovic ivan.miljeno...@gmail.com IvanMiljenovic.wordpress.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Is my code too complicated?
Hello fellow Haskellers, I'd like to discuss an interesting topic. My experience is that there are two worlds in Haskell, which are quite separate: the pure, algorithmic world, where you use idiomatic pure Haskell, and the IO-driven world of state, change, threads and execution, where you use idiomatic concurrent Haskell. If you understand these two concepts well, then you are usually a good Haskell programmer. Interestingly this doesn't mean that you get applications done faster or done at all. Most languages today provide a certain "glue" to bring everything together. I think that term originates from "Why Functional Programming Matters" by John Hughes. Haskell provides a lot of low level glue like laziness, currying and other very helpful language features. But what is different in Haskell is that it doesn't seem to provide any high level glue like other languages do, especially when it comes to the IO world. There is a somewhat powerful module system, but nothing to bring modules and the objects they define together in a consistent way. In my opinion this is both a disadvantage and an advantage. It's bad because there is no standard way of gluing, nothing everybody learns and uses. On the other hand it's good, because you can make your own glue. This has proven very useful for me. My usual way is writing monad transformers and sticking them together, often together with concurrent programming. The problem with that approach is: This makes my code harder to understand for beginners. Usually they can tell /what/ my code is doing, because it's written in natural language as much as possible, but they couldn't reproduce it. And when they try to learn it, they give up fast, because you need quite some background for that. Also sometimes when I write Haskell, my friend sits beside me and watches. When he asks (as a PHP programmer with some C background), say, about my types, I can't give a brief explanation like I could in other languages. Yesterday I was writing a toy texture handler for OpenGL (for loading and selecting textures). He asked about my TextureT type. I couldn't explain it, because you couldn't even express such a thing in PHP or C. type TextureT = StateT Config -- Note that this is MonadLib. -- BaseM m IO corresponds to MonadIO m. selectTexture :: BaseM m IO => B.ByteString -> TextureT m () I fear that my code is already too difficult to understand for beginners, and it's getting worse. But then I ask myself: I've got a powerful language, so why shouldn't I use that power? After all I haven't learnt Haskell to write C code with it. And a new Haskell programmer doesn't read my code to learn Haskell. They first learn Haskell and /then/ read my code. Is this a real problem or am I just exaggerating? What do you think? Greets, Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://ertes.de/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe