[Haskell-cafe] Re: Suggestions for an MSc Project?
None of the frameworks in http://www.haskell.org/haskellwiki/Applications_and_libraries/GUI_libraries#High-level appear to have a working build in http://hackage.haskell.org/packages/archive/pkg-list.html#cat:gui, except wxFruit. Is there a need that isn't being met for high-level GUI libraries? Another suggestion I received in a private reply is to work on data persistence, but it would be tough to evaluate all the dozens of entries in http://hackage.haskell.org/packages/archive/pkg-list.html#cat:database. Is there some database need that isn't being met? I've never done serious Haskell programming (I've played with it a little while doing lots of C# at work), so I'm hoping that more experienced Haskell programmers could identify a potentially useful contribution. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] music-related problem
erik flister wrote: Michael Mossey wrote: Regarding my use of Rational, it's because I'm representing *notated* durations or positions in time, which are always fractions of integers. Suppose I give the command to my program to play via midi everything from bar 1 beat 1 to bar 2 beat 2 1/2. I want to use Rational so I know 2 1/2 means 2 1/2 and not 2.499. i wasn't suggesting anything Numeric for durations -- those are NoteDurs like (Dotted $ Triplet Half). you don't need numerics until resolving temporal locations, like milliseconds or subdivisions of a beat. those may be irrational numbers (consider if the tempo is irrational, or tiny random jitter in timing) -- though it's a totally pedantic point on my part and realistically won't matter. ;) We must be addressing different problems. My software doesn't have much interest in the concept of eighth notes or dotted notes. What I want to do is process a musical document to answer questions like this: - what notes have onset times between measure 1 beat 1 and measure 1 beat 3? - organize the document into verticals: notes that occur at the same time in any part - what notes finish sounding before measure 4? In music, the passage of time has two meanings. One meaning is provided by the notation: on what beats notes occur and how they last (in terms of beats). This is independent of tempo, rit, accel. Call this score time. The other meaning is real-world performance in which tempo, rit, accel, trills and tremolos are realized. Call this real time. For the first meaning, my program will find it simple and useful to represent time as measure (Int) and beat (Rational --- or perhaps anything in class Fractional (I have to study this more)). If I tried to represent score time as eighth notes or whatever it would drive me crazy. I have no need to do that. (Note that this level of time representation is not intended for a human interface.) Score time can involve fractions composed from numbers greater than four---like 7-tuplets. But to my knowledge, there is no way to notate something that cannot be represented by a fraction. Real time is better represented as floating point. It is derived from tempos and tempo maps. Thanks, Mike ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Is my code too complicated?
Felipe Lessa felipe.le...@gmail.com wrote: On Sat, Jul 3, 2010 at 9:25 AM, Ertugrul Soeylemez e...@ertes.de 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. I found that I get along with the basic concurrency constructs. STM may be handy in a few applications, but in none that I write. 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? Not really. Even when programming in such a style, Haskell is much safer than PHP with its braindead type system, and still somewhat safer than C. 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. I find monad transformers easy to reason about, and in most cases the stacking order doesn't make a difference at all. Just remember to change the running function, too. The problem with them is that beginners learn them very late. 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. Then you need to explain type of functions and this explicitly implicit state and why you have to do it that way in Haskell. 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
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 5 July 2010 10:39, Yves Parès limestr...@gmail.com 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
[Haskell-cafe] Re: Is my code too complicated?
Stephen Tetley stephen.tet...@gmail.com wrote: On 5 July 2010 10:39, Yves Parès limestr...@gmail.com 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...) That's what monad transformers are good for. Why reinvent the wheel? type Amalgamated s e m = MaybeT (StateT s (ReaderT e m)) This is all you need to create your own monad with the specified functionality. testComp :: Amalgamated Int Bool IO () testComp = do x - return (Just 3) y - ask z0 - get when y $ sets_ (+1) z1 - get inBase $ print (x, y, z0, z1) However, MaybeT as defined in the 'MaybeT' package will probably not work here. But this is not a transformer-related problem, just compatibility. 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
Re: [Haskell-cafe] How easy is it to hire Haskell programmers
On Fri, Jul 2, 2010 at 15:43, Edward Kmett wrote: I've had a fairly easy time of hiring Haskell programmers. Does this mean your company actively uses Haskell in projects? Would you be willing/able to describe this work in more detail for the curious? Sean ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Is my code too complicated?
On Mon, Jul 5, 2010 at 6:12 AM, Ertugrul Soeylemez e...@ertes.de wrote: Felipe Lessa felipe.le...@gmail.com wrote: On Sat, Jul 3, 2010 at 9:25 AM, Ertugrul Soeylemez e...@ertes.de 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. I found that I get along with the basic concurrency constructs. STM may be handy in a few applications, but in none that I write. STM has the same basic concurrency constructs, but they are safe to use. MVars and everything derived from them have tricky semantics that can fail in catastrofic ways. Neil Mitchell was recently trying to find a subtle bug in his code because of MVars and Chans. Cheers! -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Criteria for determining if a recursive function can be implemented in constant memory
Dear Cafe, since a little discussion with my tutor I am wondering how the following problem can be solved and if it is decidable: Given the definition of a recursive function f in, say, haskell, determine if f can be implemented in O(1) memory. First I thought the solution would be check if f is tail-recursive. However, consider the following definition: -- for the sake of uniformity if' c t e = if c then t else e f :: (Num a) = a - a - a f x y = if' (x = 0) y $ if' (x = 2) (f (x-2) (y+1)) (f (x-1) y) (I don't really care what this function computes as long as it terminates, which is obvious) Although ghc will probably not perform this optimization, f can be realized in O(1) mem: // trying to duplicate f's structure as closely as possible double f( double x, double y ) { START: if ( x = 0 ) return y; else { if ( x = 2 ) { x = x - 2; y = y + 1; goto START; } else { x = x - 1; y = y; goto START; } } } It is crucial that (the second) if' does not use both of its last two arguments, but only one. If we replace the second if' by, say g :: (Num a) = c - a - a - a g c t e = if' c (t + e) (t - e) , then we have to compute *both* (f (x-2) (y+1)) and (f (x-1) y), and x and y have to be kept in memory during the call to (f (x-2) (y+1)), therefore f cannot be implemented in constant memory. (read: I haven't found a way which does not radically alter f's structure). So, does someone know how to solve this or can prove that it can't be solved? Best regards, Steffen ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Fwd: [Haskell-cafe] Re: Is my code too complicated?
Very often the type system assures safety to a point where some coding is done trough trial and error: -I think that this composition is right, let´s try it-... -oh, some missing type here, Let´s put it here and here-...-go on-... -The typechecker say t´s OK. I run it and, well it works. Later when I look at the code, I have to think twice to understand it. Sometimes I mix transactions, threading, IO and some other abstractions in the same line, things that I would fear much to work with in any other language. This playing thig is fine, because the typechecking cut a lot of dead branches in the entrophic tendency of humans to commit mistakes. For this matter I praise math as the hidden god that handles reality and haskell its prophet. but the resulting code is not a product of my intended design, but something made together with the compiler, and sometimes it needs more than a look to understand it, even to myself. 2010/7/5 Ertugrul Soeylemez e...@ertes.de Felipe Lessa felipe.le...@gmail.com wrote: On Sat, Jul 3, 2010 at 9:25 AM, Ertugrul Soeylemez e...@ertes.de 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. I found that I get along with the basic concurrency constructs. STM may be handy in a few applications, but in none that I write. 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? Not really. Even when programming in such a style, Haskell is much safer than PHP with its braindead type system, and still somewhat safer than C. 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. I find monad transformers easy to reason about, and in most cases the stacking order doesn't make a difference at all. Just remember to change the running function, too. The problem with them is that beginners learn them very late. 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. Then you need to explain type of functions and this explicitly implicit state and why you have to do it that way in Haskell. 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Criteria for determining if a recursive function can be implemented in constant memory
Hi Steffen, Steffen Schuldenzucker wrote: since a little discussion with my tutor I am wondering how the following problem can be solved and if it is decidable: Given the definition of a recursive function f in, say, haskell, determine if f can be implemented in O(1) memory. Constant functions are implementable in O(1) memory, but interpreters for turing-complete languages are not, so the property of being implementable in O(1) memory is non-trivial and therefore, by Rice's theorem, undecidable. Tillmann ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Subtype polymorphism in Haskell
Hi, I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me? Roughly, the class hierarchy in C++ is of the form class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; Any help would be greatly appreciated. Thanks Simon courten...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Is my code too complicated?
On 5 July 2010 11:30, Ertugrul Soeylemez e...@ertes.de wrote: That's what monad transformers are good for. Why reinvent the wheel? Hi Ertugrul The post was chiming in with Felipe Lessa's comment upthread that avoiding transfomers can have performance benefits. Whether the formulation I gave is particulary efficient is moot - I'd have to give consideration to the strictness of the state at least - but I was answering Yves Parès about how you would do it, rather than why. Given the status of MTL, I nowadays avoid transformers for pragmatic reasons rather than performance ones. If I have substantial code I'll rely on Iavor S. Diatchki's very nice MonadLib, but for small projects I'll just roll an amalgamated monad. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Subtype polymorphism in Haskell
My guess is that it's class B : public A and class C : public A In this case it seems perfect to use type classes: class A t where do_x :: t - Integer - Integer - Integer data B = ... instance A B where do_x b x y = ... data C = ... instance A C where do_x c x y = ... If you want some general A object, you can use existentials (or, better yet, GADTs): data A_general = forall t. A t = A_general t or data A_GADT where A_GADT :: A t = t - A_GADT so that int foo (A v) {... v.do_x(1,2)...} becomes foo :: A_GADT - Integer foo (A_GADT v) = ... do_x v 1 2 ... Simon Courtenage wrote: Hi, I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me? Roughly, the class hierarchy in C++ is of the form class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; Any help would be greatly appreciated. Thanks Simon courten...@gmail.com mailto:courten...@gmail.com ___ 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] Subtype polymorphism in Haskell
On Monday 05 July 2010 15:22:43, Simon Courtenage wrote: Hi, I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me? Roughly, the class hierarchy in C++ is of the form class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; Any help would be greatly appreciated. If there's not more to it, class A where do_x :: Int - Int - Int instance A B where do_x = whatever instance A C where do_x = somethingElse would solve it. Thanks Simon courten...@gmail.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Is my code too complicated?
Felipe Lessa felipe.le...@gmail.com wrote: On Mon, Jul 5, 2010 at 6:12 AM, Ertugrul Soeylemez e...@ertes.de wrote: Felipe Lessa felipe.le...@gmail.com wrote: On Sat, Jul 3, 2010 at 9:25 AM, Ertugrul Soeylemez e...@ertes.de 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. I found that I get along with the basic concurrency constructs. STM may be handy in a few applications, but in none that I write. STM has the same basic concurrency constructs, but they are safe to use. MVars and everything derived from them have tricky semantics that can fail in catastrofic ways. Neil Mitchell was recently trying to find a subtle bug in his code because of MVars and Chans. It happened once to me that I forgot that MVars don't have a queue. A database thread would take values out of the MVar as commands and execute them, but I used the same thread to put a command into the MVar (for later execution). It worked most of the time, unless another thread put a command concurrently, right after the last command was executed and before the database thread put another command ⇒ deadlock. I fixed this by replacing the MVar by a Chan. Could STM have helped here? And as a related question, how fast does STM perform in average? Is it suitable for high traffic applications (not network/file traffic, but MVar/Chan traffic)? Usually in a non-SMP setting I can easily pass hundreds of thousands of values per second through MVars between tens of thousands of threads. 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
Re: [Haskell-cafe] Subtype polymorphism in Haskell
Does this work for you? data A a = A (Int,Int) data B data C class A_Class a where do_x :: a - Int instance A_Class (A B) where do_x (A (a,b)) = a + b instance A_Class (A C) where do_x (A (a,b)) = a - b -- do_x ((A (1,2)) :: A B) -- 3 -- do_x ((A (1,2)) :: A C) -- -1 -deech On Mon, Jul 5, 2010 at 9:22 AM, Simon Courtenage courten...@gmail.com wrote: Hi, I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. Can anyone enlighten me? Roughly, the class hierarchy in C++ is of the form class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; Any help would be greatly appreciated. Thanks Simon courten...@gmail.com ___ 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
[Haskell-cafe] Re: Is my code too complicated?
Stephen Tetley stephen.tet...@gmail.com wrote: On 5 July 2010 11:30, Ertugrul Soeylemez e...@ertes.de wrote: That's what monad transformers are good for. Why reinvent the wheel? The post was chiming in with Felipe Lessa's comment upthread that avoiding transfomers can have performance benefits. Whether the formulation I gave is particulary efficient is moot - I'd have to give consideration to the strictness of the state at least - but I was answering Yves Parès about how you would do it, rather than why. Yes, there is some performance loss because of wrapping/unwrapping, but I think this loss is neglible for most applications. And I'd ask anyway. This is a discussion thread after all. =) Given the status of MTL, I nowadays avoid transformers for pragmatic reasons rather than performance ones. If I have substantial code I'll rely on Iavor S. Diatchki's very nice MonadLib, but for small projects I'll just roll an amalgamated monad. Almost all of my projects, including one published one, depend on monadLib. I find the MTL comparatively inconvenient. And especially for small projects I don't see why I should roll my own monad. I prefer to stick some transformers together. For larger applications my criterion is speed, but I've yet to see an application, where transformers are too slow. 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
Re: [Haskell-cafe] More experiments with ATs
On Sun, Jul 04, 2010 at 10:31:34AM +0100, Andrew Coppin wrote: I have literally no idea what a type family is. I understand ATs (I think!), but TFs make no sense to me. ATs are just TFs which happen to be associated with a particular class. So if you understand ATs then you understand TFs too, you just didn't know it. =) -Brent ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Subtype polymorphism in Haskell
Simon Courtenage wrote: I am porting a C++ program to Haskell. My current task is to take a class hierarchy and produce something equivalent in Haskell, but I don't seem to be able to get a grip on how type classes and instances contribute to the solution. They probably do not contribute at all. class A { public: virtual int do_x(int,int) = 0; }; class B { public: int do_x(int x,int y) { ...} }; class C { public: int do_x(int x,int y) { ...} }; I guess B and C are subclasses of A? If you do not need complicated subtyping schemes, you could consider on of the following two options: You could emphasize the structure of the class hierarchy, or you could emphasize the object abstraction. The structure of the class hierarchy could be represented by an algebraic data type data A = B | C with the do_x function implementing by pattern matching on an A value do_x :: A - Int - Int - Int do_x B = ... do_x C = ... If your classes have fields, they could be added as fields to the data constructors B and C. Alternatively, the object abstraction could be represented by encoding objects as records of first-class functions. data A = A { do_x :: Int - Int - Int } b = A {do_x = \x y - ...} c = A {do_x = \x y - ...} If your classes have fields, they could be added as arguments to constructor functions b and c. Tillmann ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Getting started
This really helped, but now I am trying to add a new track to the database using a menu but it won't compile. I have tried a lot of different things but to no avail. When I get rid of the menu I am able to run, for example, newRecord This Charming Man The Smiths 1 [] This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. Thanks for your help previously, Jack type Title = String type Artist = String type Sold = Int type Sales = Sales Record type Record = (Title, Artist, Sold) testDatabase :: [Sales] testDatabase = [(Sales Jack Waters 2)] --recordSale :: Sales - String - String - Sales --recordSale title artist = (title, artist) newRecord :: Record - [Sales] - [Sales] newRecord title artist sold dbase = (title, artist, sold):dbase recordSale :: Record - [Sales] recordSale record sales = sold + 1 main :: [Sales] - IO() main dbase = do putStrLn 1 = Add a new record: input - getLine let x = read input :: Int if x == 1 then do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt newRecord (Sales title artist sales []) dbase Holger Siegel wrote: Am 01.07.2010 um 21:56 schrieb Mrwibbly: I'm having real trouble starting this project. Basically I have to create a record store that store information about artists and albums and also the number of sales that they have had. It also needs to generate a list of the top 5 sellers. So far I have: recordSale :: Sales - String - String - Sales where recordSale sales anArtist aTrack returns a modified version of the sales. Any help getting started on this would be gratefully received. I don't want answers, I just want help getting started. First, I would state explicitly what a record is: It is a tuple of an artist's name and a record's name type Record = (String, String) Now function recordSale has type recordSale :: Sales - Record - Sales This is the an uncurried equivalent of your definition. You can read it as from a sales object you get to another sales object via a (sold) record. That already seems to be a good abstraction, but we can do better: If you flip the arguments, you get recordSale :: Record - Sales - Sales Now you can create a sale (recordSale (Zappa, Apostrophe)). This sale is a function of type (Sales - Sales) that modifies your sales. We state this by defining type Sale = Sales - Sales recordSale :: Record - Sale Sales can be concatenated with the dot operator (.) and there is even a neutral sale, the function 'id'. Thus, you know immediately that for any sales x,y,z there is (x . (y . z) == (x . y) . z) and (x . id == x). In other words, it forms a monoid - just like the number of sales together with (+) and 0! If you're only interested in the number of sales, you can simply define type Sales = Integer recordSale record sales = sales + 1 But you don't want to keep track of the whole number of sales - you want a number for every record you have sold. That means, you need a data structure that maps records to their number of sales: import Data.Map type Sales = Map Record Integer It's a bit tricky to find an implementation for recordSale. Think of how you can combine two arbitrary Sales objects before you try to implement it. Regards, Holger ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/Getting-started-tp29046956p29073993.html 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] Getting started
Does this code compile? The line type Sales = Sales Record for instance is wrong - it should be data Sales = Sales Record. Additionally recordSale returns an Int, not [Sales]. -deech On Mon, Jul 5, 2010 at 10:50 AM, Mrwibbly jackwater...@googlemail.com wrote: This really helped, but now I am trying to add a new track to the database using a menu but it won't compile. I have tried a lot of different things but to no avail. When I get rid of the menu I am able to run, for example, newRecord This Charming Man The Smiths 1 [] This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. Thanks for your help previously, Jack type Title = String type Artist = String type Sold = Int type Sales = Sales Record type Record = (Title, Artist, Sold) testDatabase :: [Sales] testDatabase = [(Sales Jack Waters 2)] --recordSale :: Sales - String - String - Sales --recordSale title artist = (title, artist) newRecord :: Record - [Sales] - [Sales] newRecord title artist sold dbase = (title, artist, sold):dbase recordSale :: Record - [Sales] recordSale record sales = sold + 1 main :: [Sales] - IO() main dbase = do putStrLn 1 = Add a new record: input - getLine let x = read input :: Int if x == 1 then do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt newRecord (Sales title artist sales []) dbase Holger Siegel wrote: Am 01.07.2010 um 21:56 schrieb Mrwibbly: I'm having real trouble starting this project. Basically I have to create a record store that store information about artists and albums and also the number of sales that they have had. It also needs to generate a list of the top 5 sellers. So far I have: recordSale :: Sales - String - String - Sales where recordSale sales anArtist aTrack returns a modified version of the sales. Any help getting started on this would be gratefully received. I don't want answers, I just want help getting started. First, I would state explicitly what a record is: It is a tuple of an artist's name and a record's name type Record = (String, String) Now function recordSale has type recordSale :: Sales - Record - Sales This is the an uncurried equivalent of your definition. You can read it as from a sales object you get to another sales object via a (sold) record. That already seems to be a good abstraction, but we can do better: If you flip the arguments, you get recordSale :: Record - Sales - Sales Now you can create a sale (recordSale (Zappa, Apostrophe)). This sale is a function of type (Sales - Sales) that modifies your sales. We state this by defining type Sale = Sales - Sales recordSale :: Record - Sale Sales can be concatenated with the dot operator (.) and there is even a neutral sale, the function 'id'. Thus, you know immediately that for any sales x,y,z there is (x . (y . z) == (x . y) . z) and (x . id == x). In other words, it forms a monoid - just like the number of sales together with (+) and 0! If you're only interested in the number of sales, you can simply define type Sales = Integer recordSale record sales = sales + 1 But you don't want to keep track of the whole number of sales - you want a number for every record you have sold. That means, you need a data structure that maps records to their number of sales: import Data.Map type Sales = Map Record Integer It's a bit tricky to find an implementation for recordSale. Think of how you can combine two arbitrary Sales objects before you try to implement it. Regards, Holger ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/Getting-started-tp29046956p29073993.html 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Getting started
You said it didn't compile. I somehow missed that , sorry. -deech On Mon, Jul 5, 2010 at 11:06 AM, aditya siram aditya.si...@gmail.com wrote: Does this code compile? The line type Sales = Sales Record for instance is wrong - it should be data Sales = Sales Record. Additionally recordSale returns an Int, not [Sales]. -deech On Mon, Jul 5, 2010 at 10:50 AM, Mrwibbly jackwater...@googlemail.com wrote: This really helped, but now I am trying to add a new track to the database using a menu but it won't compile. I have tried a lot of different things but to no avail. When I get rid of the menu I am able to run, for example, newRecord This Charming Man The Smiths 1 [] This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. Thanks for your help previously, Jack type Title = String type Artist = String type Sold = Int type Sales = Sales Record type Record = (Title, Artist, Sold) testDatabase :: [Sales] testDatabase = [(Sales Jack Waters 2)] --recordSale :: Sales - String - String - Sales --recordSale title artist = (title, artist) newRecord :: Record - [Sales] - [Sales] newRecord title artist sold dbase = (title, artist, sold):dbase recordSale :: Record - [Sales] recordSale record sales = sold + 1 main :: [Sales] - IO() main dbase = do putStrLn 1 = Add a new record: input - getLine let x = read input :: Int if x == 1 then do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt newRecord (Sales title artist sales []) dbase Holger Siegel wrote: Am 01.07.2010 um 21:56 schrieb Mrwibbly: I'm having real trouble starting this project. Basically I have to create a record store that store information about artists and albums and also the number of sales that they have had. It also needs to generate a list of the top 5 sellers. So far I have: recordSale :: Sales - String - String - Sales where recordSale sales anArtist aTrack returns a modified version of the sales. Any help getting started on this would be gratefully received. I don't want answers, I just want help getting started. First, I would state explicitly what a record is: It is a tuple of an artist's name and a record's name type Record = (String, String) Now function recordSale has type recordSale :: Sales - Record - Sales This is the an uncurried equivalent of your definition. You can read it as from a sales object you get to another sales object via a (sold) record. That already seems to be a good abstraction, but we can do better: If you flip the arguments, you get recordSale :: Record - Sales - Sales Now you can create a sale (recordSale (Zappa, Apostrophe)). This sale is a function of type (Sales - Sales) that modifies your sales. We state this by defining type Sale = Sales - Sales recordSale :: Record - Sale Sales can be concatenated with the dot operator (.) and there is even a neutral sale, the function 'id'. Thus, you know immediately that for any sales x,y,z there is (x . (y . z) == (x . y) . z) and (x . id == x). In other words, it forms a monoid - just like the number of sales together with (+) and 0! If you're only interested in the number of sales, you can simply define type Sales = Integer recordSale record sales = sales + 1 But you don't want to keep track of the whole number of sales - you want a number for every record you have sold. That means, you need a data structure that maps records to their number of sales: import Data.Map type Sales = Map Record Integer It's a bit tricky to find an implementation for recordSale. Think of how you can combine two arbitrary Sales objects before you try to implement it. Regards, Holger ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/Getting-started-tp29046956p29073993.html 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Getting started
I changed that line to say type Sales = Sales Record. But unfortunately it still fails to compile. Do you have any idea why this might be the case? -Jack aditya siram-2 wrote: You said it didn't compile. I somehow missed that , sorry. -deech On Mon, Jul 5, 2010 at 11:06 AM, aditya siram aditya.si...@gmail.com wrote: Does this code compile? The line type Sales = Sales Record for instance is wrong - it should be data Sales = Sales Record. Additionally recordSale returns an Int, not [Sales]. -deech On Mon, Jul 5, 2010 at 10:50 AM, Mrwibbly jackwater...@googlemail.com wrote: This really helped, but now I am trying to add a new track to the database using a menu but it won't compile. I have tried a lot of different things but to no avail. When I get rid of the menu I am able to run, for example, newRecord This Charming Man The Smiths 1 [] This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. Thanks for your help previously, Jack type Title = String type Artist = String type Sold = Int type Sales = Sales Record type Record = (Title, Artist, Sold) testDatabase :: [Sales] testDatabase = [(Sales Jack Waters 2)] --recordSale :: Sales - String - String - Sales --recordSale title artist = (title, artist) newRecord :: Record - [Sales] - [Sales] newRecord title artist sold dbase = (title, artist, sold):dbase recordSale :: Record - [Sales] recordSale record sales = sold + 1 main :: [Sales] - IO() main dbase = do putStrLn 1 = Add a new record: input - getLine let x = read input :: Int if x == 1 then do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt newRecord (Sales title artist sales []) dbase Holger Siegel wrote: Am 01.07.2010 um 21:56 schrieb Mrwibbly: I'm having real trouble starting this project. Basically I have to create a record store that store information about artists and albums and also the number of sales that they have had. It also needs to generate a list of the top 5 sellers. So far I have: recordSale :: Sales - String - String - Sales where recordSale sales anArtist aTrack returns a modified version of the sales. Any help getting started on this would be gratefully received. I don't want answers, I just want help getting started. First, I would state explicitly what a record is: It is a tuple of an artist's name and a record's name type Record = (String, String) Now function recordSale has type recordSale :: Sales - Record - Sales This is the an uncurried equivalent of your definition. You can read it as from a sales object you get to another sales object via a (sold) record. That already seems to be a good abstraction, but we can do better: If you flip the arguments, you get recordSale :: Record - Sales - Sales Now you can create a sale (recordSale (Zappa, Apostrophe)). This sale is a function of type (Sales - Sales) that modifies your sales. We state this by defining type Sale = Sales - Sales recordSale :: Record - Sale Sales can be concatenated with the dot operator (.) and there is even a neutral sale, the function 'id'. Thus, you know immediately that for any sales x,y,z there is (x . (y . z) == (x . y) . z) and (x . id == x). In other words, it forms a monoid - just like the number of sales together with (+) and 0! If you're only interested in the number of sales, you can simply define type Sales = Integer recordSale record sales = sales + 1 But you don't want to keep track of the whole number of sales - you want a number for every record you have sold. That means, you need a data structure that maps records to their number of sales: import Data.Map type Sales = Map Record Integer It's a bit tricky to find an implementation for recordSale. Think of how you can combine two arbitrary Sales objects before you try to implement it. Regards, Holger ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context: http://old.nabble.com/Getting-started-tp29046956p29073993.html 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 ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- View this message in context:
Re: [Haskell-cafe] Getting started
Yes there are a few more problems. Instead of point out each one here is some modified code that does compile. Compare it to what you have and let me know if you have questions: type Title = String type Artist = String type Sold = Int type Record = (Title, (Artist, Sold)) testDatabase :: [Record] testDatabase = [(Jack, (Waters, 2))] newRecord :: Record - [Record] - [Record] newRecord record dbase = [record] ++ dbase getTitle :: Record - Title getTitle (title,_) = title addSale :: Record - Record addSale (title, (artist,sold)) = (title, (artist, sold + 1)) recordSale :: Record - [Record] - [Record] recordSale r@(title, (artist,sold)) sales = case (Prelude.lookup title sales) of Nothing - error This record does not exist Just x - [addSale r] ++ (filter (\a - (getTitle a) /= title) sales) addRecord :: IO Record addRecord = do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt return (title , (artist, sales)) where getInt :: IO Int getInt = getLine = return . read On Mon, Jul 5, 2010 at 11:36 AM, Mrwibbly jackwater...@googlemail.com wrote: I changed that line to say type Sales = Sales Record. But unfortunately it still fails to compile. Do you have any idea why this might be the case? -Jack aditya siram-2 wrote: You said it didn't compile. I somehow missed that , sorry. -deech On Mon, Jul 5, 2010 at 11:06 AM, aditya siram aditya.si...@gmail.com wrote: Does this code compile? The line type Sales = Sales Record for instance is wrong - it should be data Sales = Sales Record. Additionally recordSale returns an Int, not [Sales]. -deech On Mon, Jul 5, 2010 at 10:50 AM, Mrwibbly jackwater...@googlemail.com wrote: This really helped, but now I am trying to add a new track to the database using a menu but it won't compile. I have tried a lot of different things but to no avail. When I get rid of the menu I am able to run, for example, newRecord This Charming Man The Smiths 1 [] This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. Thanks for your help previously, Jack type Title = String type Artist = String type Sold = Int type Sales = Sales Record type Record = (Title, Artist, Sold) testDatabase :: [Sales] testDatabase = [(Sales Jack Waters 2)] --recordSale :: Sales - String - String - Sales --recordSale title artist = (title, artist) newRecord :: Record - [Sales] - [Sales] newRecord title artist sold dbase = (title, artist, sold):dbase recordSale :: Record - [Sales] recordSale record sales = sold + 1 main :: [Sales] - IO() main dbase = do putStrLn 1 = Add a new record: input - getLine let x = read input :: Int if x == 1 then do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt newRecord (Sales title artist sales []) dbase Holger Siegel wrote: Am 01.07.2010 um 21:56 schrieb Mrwibbly: I'm having real trouble starting this project. Basically I have to create a record store that store information about artists and albums and also the number of sales that they have had. It also needs to generate a list of the top 5 sellers. So far I have: recordSale :: Sales - String - String - Sales where recordSale sales anArtist aTrack returns a modified version of the sales. Any help getting started on this would be gratefully received. I don't want answers, I just want help getting started. First, I would state explicitly what a record is: It is a tuple of an artist's name and a record's name type Record = (String, String) Now function recordSale has type recordSale :: Sales - Record - Sales This is the an uncurried equivalent of your definition. You can read it as from a sales object you get to another sales object via a (sold) record. That already seems to be a good abstraction, but we can do better: If you flip the arguments, you get recordSale :: Record - Sales - Sales Now you can create a sale (recordSale (Zappa, Apostrophe)). This sale is a function of type (Sales - Sales) that modifies your sales. We state this by defining type Sale = Sales - Sales recordSale :: Record - Sale Sales can be concatenated with the dot operator (.) and there is even a neutral sale, the function 'id'. Thus, you know immediately that for any sales x,y,z there is (x . (y . z) == (x . y) . z) and (x . id == x). In other words, it forms a monoid - just like the number of sales together with (+) and 0! If you're only interested in the number of sales, you can simply define type Sales =
Re: [Haskell-cafe] Getting started
And here's a more sane version of recordSale: recordSale' :: Title - [Record] - [Record] recordSale' title sales = case (Prelude.lookup title sales) of Nothing - error This record does not exist Just x - [addSale (title,x)] ++ (filter (\a - (getTitle a) /= title) sales) -deech On Mon, Jul 5, 2010 at 11:39 AM, aditya siram aditya.si...@gmail.com wrote: Yes there are a few more problems. Instead of point out each one here is some modified code that does compile. Compare it to what you have and let me know if you have questions: type Title = String type Artist = String type Sold = Int type Record = (Title, (Artist, Sold)) testDatabase :: [Record] testDatabase = [(Jack, (Waters, 2))] newRecord :: Record - [Record] - [Record] newRecord record dbase = [record] ++ dbase getTitle :: Record - Title getTitle (title,_) = title addSale :: Record - Record addSale (title, (artist,sold)) = (title, (artist, sold + 1)) recordSale :: Record - [Record] - [Record] recordSale r@(title, (artist,sold)) sales = case (Prelude.lookup title sales) of Nothing - error This record does not exist Just x - [addSale r] ++ (filter (\a - (getTitle a) /= title) sales) addRecord :: IO Record addRecord = do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt return (title , (artist, sales)) where getInt :: IO Int getInt = getLine = return . read On Mon, Jul 5, 2010 at 11:36 AM, Mrwibbly jackwater...@googlemail.com wrote: I changed that line to say type Sales = Sales Record. But unfortunately it still fails to compile. Do you have any idea why this might be the case? -Jack aditya siram-2 wrote: You said it didn't compile. I somehow missed that , sorry. -deech On Mon, Jul 5, 2010 at 11:06 AM, aditya siram aditya.si...@gmail.com wrote: Does this code compile? The line type Sales = Sales Record for instance is wrong - it should be data Sales = Sales Record. Additionally recordSale returns an Int, not [Sales]. -deech On Mon, Jul 5, 2010 at 10:50 AM, Mrwibbly jackwater...@googlemail.com wrote: This really helped, but now I am trying to add a new track to the database using a menu but it won't compile. I have tried a lot of different things but to no avail. When I get rid of the menu I am able to run, for example, newRecord This Charming Man The Smiths 1 [] This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. Thanks for your help previously, Jack type Title = String type Artist = String type Sold = Int type Sales = Sales Record type Record = (Title, Artist, Sold) testDatabase :: [Sales] testDatabase = [(Sales Jack Waters 2)] --recordSale :: Sales - String - String - Sales --recordSale title artist = (title, artist) newRecord :: Record - [Sales] - [Sales] newRecord title artist sold dbase = (title, artist, sold):dbase recordSale :: Record - [Sales] recordSale record sales = sold + 1 main :: [Sales] - IO() main dbase = do putStrLn 1 = Add a new record: input - getLine let x = read input :: Int if x == 1 then do putStrLn Please enter a title: title - getLine putStrLn Please enter an artist name: artist - getLine putStrLn Please enter the number sales: sales - getInt newRecord (Sales title artist sales []) dbase Holger Siegel wrote: Am 01.07.2010 um 21:56 schrieb Mrwibbly: I'm having real trouble starting this project. Basically I have to create a record store that store information about artists and albums and also the number of sales that they have had. It also needs to generate a list of the top 5 sellers. So far I have: recordSale :: Sales - String - String - Sales where recordSale sales anArtist aTrack returns a modified version of the sales. Any help getting started on this would be gratefully received. I don't want answers, I just want help getting started. First, I would state explicitly what a record is: It is a tuple of an artist's name and a record's name type Record = (String, String) Now function recordSale has type recordSale :: Sales - Record - Sales This is the an uncurried equivalent of your definition. You can read it as from a sales object you get to another sales object via a (sold) record. That already seems to be a good abstraction, but we can do better: If you flip the arguments, you get recordSale :: Record - Sales - Sales Now you can create a sale (recordSale (Zappa, Apostrophe)). This sale is a function of type (Sales - Sales) that modifies your sales. We state this by defining type Sale = Sales - Sales recordSale :: Record - Sale Sales can be
Re: [Haskell-cafe] Getting started
On Jul 5, 2010, at 7:50 AM, Mrwibbly wrote: This adds the data to an empty database but I can't seem to call newRecord again and add another record to the existing database. The issue is that you need to use the new database returned by newRecord in subsequent executions of your main loop. I've coded a simpler data example showing how to do this: -- -- Pure, Functional Data Set -- type Name = String type DB = [Name] addName :: String - DB - DB addName name db = name : db initialDB :: DB initialDB = [ Amy, Bob ] -- -- UI Actions on DBs -- addNameAction :: DB - IO DB addNameAction db = do putStrLn Enter name to add: name - getLine return $ addName name db printNames :: DB - IO () printNames db = mapM_ print db -- -- Main Program -- mainLoop :: DB - IO () mainLoop db = do putStrLn 1 = Add a name to the DB putStrLn 2 = Print the DB putStrLn 3 = Exit input - getLine case read input of 1 - do newDB - addNameAction db mainLoop newDB 2 - do printNames db mainLoop db 3 - do return () main :: IO () main = mainLoop initialDB Notice how mainLoop is called recursively after the input is handled. This is how the changes to the database are propagated from one action to the next. Note: mainLoop is rather verbose, you would generally find this written as: mainLoop :: DB - IO () mainLoop db = do putStrLn 1 = Add a name to the DB putStrLn 2 = Print the DB putStrLn 3 = Exit input - getLine case read input of 1 - addNameAction db = mainLoop 2 - printNames db mainLoop db 3 - return () Once you've got that under your belt, consider this version, which is even more general: actions :: [(String, DB - IO ())] actions = [ (Add a name to the DB,\db - addNameAction db = mainLoop), (Print the DB,\db - printNames db mainLoop db), (Exit,\db - return ()) ] mainLoop :: DB - IO () mainLoop db = do mapM_ print $ zip [1..] $ map fst actions input - getLine let action = snd $ actions !! (read input - 1) action db - Mark Mark Lentczner http://www.ozonehouse.com/mark/ IRC: mtnviewmark ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Criteria for determining if a recursive function can be implemented in constant memory
Tillmann Rendel wrote: Hi Steffen, Steffen Schuldenzucker wrote: Given the definition of a recursive function f in, say, haskell, determine if f can be implemented in O(1) memory. Constant functions are implementable in O(1) memory, but interpreters for turing-complete languages are not, so the property of being implementable in O(1) memory is non-trivial and therefore, by Rice's theorem, undecidable. Damn Rice's theorum, spoiling everybody's fun all the time... ;-) Of course, as I understand it, all the theorum says is that no single algorithm can give you a yes/no answer for *every* possible case. So the next question is is it decidable in any 'interesting' cases? Then of course you have to go define 'interesting'... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Is my code too complicated?
On Mon, Jul 5, 2010 at 10:29 AM, Ertugrul Soeylemez e...@ertes.de wrote: It happened once to me that I forgot that MVars don't have a queue. A database thread would take values out of the MVar as commands and execute them, but I used the same thread to put a command into the MVar (for later execution). It worked most of the time, unless another thread put a command concurrently, right after the last command was executed and before the database thread put another command ⇒ deadlock. I fixed this by replacing the MVar by a Chan. Could STM have helped here? Probably only if both puts were in the same transaction, I guess. Even with STM the solution is a channel, i.e. TChan. And as a related question, how fast does STM perform in average? Is it suitable for high traffic applications (not network/file traffic, but MVar/Chan traffic)? Usually in a non-SMP setting I can easily pass hundreds of thousands of values per second through MVars between tens of thousands of threads. As always, I guess you should benchmark :). There is some overhead, indeed, however for most applications I guess it should be fine. Specially because that overhead comes to save you from a lot of headaches. Cheers, -- Felipe. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] More experiments with ATs
Brent Yorgey wrote: On Sun, Jul 04, 2010 at 10:31:34AM +0100, Andrew Coppin wrote: I have literally no idea what a type family is. I understand ATs (I think!), but TFs make no sense to me. ATs are just TFs which happen to be associated with a particular class. So if you understand ATs then you understand TFs too, you just didn't know it. =) How would that make sense though? I'm having trouble forming a mental image of how / why you'd use that... ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Suggestions for an MSc Project?
On Mon, Jul 5, 2010 at 1:39 AM, John Smith volderm...@hotmail.com wrote: None of the frameworks in http://www.haskell.org/haskellwiki/Applications_and_libraries/GUI_libraries#High-levelappear to have a working build in http://hackage.haskell.org/packages/archive/pkg-list.html#cat:gui, except wxFruit. Is there a need that isn't being met for high-level GUI libraries? Another suggestion I received in a private reply is to work on data persistence, but it would be tough to evaluate all the dozens of entries in http://hackage.haskell.org/packages/archive/pkg-list.html#cat:database. Is there some database need that isn't being met? I've never done serious Haskell programming (I've played with it a little while doing lots of C# at work), so I'm hoping that more experienced Haskell programmers could identify a potentially useful contribution. Have you looked over Don's list of suggested summer of code projects? These were the suggested ones by Don: http://donsbot.wordpress.com/2010/04/01/the-8-most-important-haskell-org-gsoc-projects/ Here are the ones that were actually accepted: http://donsbot.wordpress.com/2010/04/26/the-7-haskell-projects-in-the-google-summer-of-code/ It seems like anything from the original list that isn't being tackled would count as an important contribution. Summer of Code is probably a smaller scope than your MSc, but that doesn't strike me as a problem. Typically in any software project, once you start working on it you can easily find room to expand it in useful directions. Similarly with the need for a research component. If you get creative you should be able to find some aspect that others haven't investigated. One thing I've been wanting lately is a good client / server, meeting scheduling / calendaring / time tracking software. Something along the lines of Meeting Maker or iCal, but open source, extensible, and with the polish of Google Calendar. I've been thinking about it a lot and I have several other usability ideas to throw in to make it really shine. I keep meaning to post my requirements on my blog. Maybe I'll get to that this week. Another thing I'd like, is to augment GHC with a type level debugger. One simple idea I had for that was to have GHC dump out the source code it's type checking with the types it has figured out (and the ones that don't type check, expect vs. inferred) annotated at every term and subterm. This has some technical hurdles, but mainly I think it has usability concerns to address. For example, how to let the user zoom in to the smallest term and see the type while also letting them select larger terms and see the type, all without being overwhelmed. Something that novices can make sense of but experts enjoy using too. Here is another idea. I'd like to see more integration between personal wikis (ones you run on localhost) and email systems. Imagine that an email comes into your inbox and then you can annotate the email by adding notes, sort of like track changes in Word. The email + notes stays in your inbox. It would be nice if you could bookmark those emails too in your web browser or similar. This would be handy for me as I sometimes reference specific emails for a long time and I often want to make notes as I reference them. Currently I paste the email into gitit and go for there. A universal interface / adapter for version control systems would be nice, but I think this one needs more research. We currently have a problem with vcs that each one speaks its own language. To me this is analogous to only being able to email people who use the same email client as you. Quite suboptimal. I hope that helps, Jason ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Subtype polymorphism in Haskell
data A_GADT where A_GADT :: A t = t - A_GADT By the way, is there an extension that enables A_GADT to be automatically declared as an instance of class A? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] [C Binding] Turning the mutable to immutable?
Hello, I don't know if some of you are familiar with the SFML library (stands for Simple and Fast Multimedia Library) -- http://sfml-dev.org As SDL, SFML is a 2D graphics library, but conversely to SDL it provides a hardware-accelerated drawing, through OpenGL. Well, I'm currently writing its Haskell binding, and I'm stuck with design issues. What I'm heading to is a full IO binding, and that's what I'd like to avoid. I particularly like the way HGL works, with the Draw monad which (IMO) enables powerful composability of the drawings. But HGL is simpler in the way that, for instance, it doesn't deal with images/sprites. So that's why I would like to pick up advice concerning the design of such a binding. First, this is how SFML (in C/C++) works: The main types are RenderWindow, Drawable, Image, Sprite, Shape, Font and Text. An Image basically represents an array of pixels. It is just a resource, and is not directly drawable. An image is loaded from a file, and provides methods for accessing/altering its pixels. Its main purpose is to be bound as an OpenGL texture. A RenderWindow is the window on which the Drawables are... well... drawn. A Sprite, now, is a Drawable. One Sprite is linked to one Image. A Sprite NEVER alters its Image, it just provides positionning/rotation/resizing/colorizing methods that will be translated, when drawing on the RenderWindow, to glTranslate/glRotate/glScale/glColor, etc. So we can see a Sprite as an instance of an Image, since if a same Image is to be drawn 3 times on the same frame, we are advised to create three Sprites of it, which will differ by their position. A Font is loaded from a file, it is a simple resource, just like Image. Text and Shape are Drawables. So, now, questions: 1) For those who know HGL, can the monad Draw principle be adapted to my case? Or am I heading for disaster? 2) How would I handle images? SFML API enables the user to alter the pixels of the image, and I obviously don't wanna copy the entire Image each time a pixel is changed. 3) Is there another library on hackage that handles images in a functional way? (I mean not *all in IO*) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Transformers versus monadLib versus...
Hey everyone, What is the current state regarding transformers versus monadLib versus mmtl versus ... etc.? Transformers seems to be the blessed replacement for mtl, so when is it worthwhile to use the other libraries instead? It hadn't even occurred to me to look closely at packages other than transformers for this purpose until I read a message earlier today from someone who said that he uses monadLib whenever he needs to use monad transformers, and it has now made me curious about them. Cheers, Greg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [C Binding] Turning the mutable to immutable?
On 07/05/2010 04:48 PM, Yves Parès wrote: 3) Is there another library on hackage that handles images in a functional way? (I mean not /all in IO/) Check out graphics-drawingcombinators. - Jake ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Transformers versus monadLib versus...
Hey everyone, What is the current state of opinion regarding transformers versus monadLib versus mmtl versus ... etc.? Transformers seems to be the blessed replacement for mtl, so when is it worthwhile to use the other libraries instead? (It hadn't even occurred to me to look closely at packages other than transformers for this purpose until I read a message earlier today from someone who said that he uses monadLib whenever he needs to use monad transformers, and it has now made me curious about them.) Cheers, Greg ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] ANNOUNCE: ghc-gc-tune: a tool for analyzing the impact of GC flags
Inspired by a comment by Simon Marlow on Stack Overflow, about the time and space tradeoffs we make with garbage collection, particularly with a generational GCs, I wrote a small program, ghc-gc-tune, to traverse the garbage collector variable space, to see the relationship between settings and program performance. Given a program, it will show you an (optionally interactive) graph of how -A and -H flags to the garbage collector affect performance. http://donsbot.wordpress.com/2010/07/05/ghc-gc-tune-tuning-haskell-gc-settings-for-fun-and-profit/ Feedback and patches welcome! -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Is my code too complicated?
On Mon, Jul 5, 2010 at 2:41 PM, Ertugrul Soeylemez e...@ertes.de wrote: Yes, there is some performance loss because of wrapping/unwrapping, but I think this loss is neglible for most applications. And I'd ask anyway. This is a discussion thread after all. =) Pretty much all monad transformers are implemented as newtypes, so the wrapping and unwrapping operations themselves should get compiled into nothing, I think. It may be that the extra type faff makes inlining or other arcane optimisations less straightforward, but I see no reason to assume that monad transformers are necessarily even slightly slower than explicitly-constructed amalgamations. In my experience, something like ReaderT Params (StateT SessionData IO) a may *look* scary, but in all your code you just use ask and put and get anyway and they all work like magic - the difficult bits are generally speaking hidden in your type synonyms and run function. But then, my largest haskell projects have never been more than a thousand or so lines, so perhaps it's just an issue of scale. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Transformers versus monadLib versus...
Gregory Crosswhite gcr...@phys.washington.edu wrote: What is the current state of opinion regarding transformers versus monadLib versus mmtl versus ... etc.? Transformers seems to be the blessed replacement for mtl, so when is it worthwhile to use the other libraries instead? (It hadn't even occurred to me to look closely at packages other than transformers for this purpose until I read a message earlier today from someone who said that he uses monadLib whenever he needs to use monad transformers, and it has now made me curious about them.) That would be me. When I was sick of flipping runWhateverT all the time, I had a closer look at the 'transformers' package. But my impression was that the only advantage is that I wouldn't need to flip anymore. I compared it to monadLib, which does a lot more. It saves me from having to do multi-lifts in complicated monads and it has a generalized MonadIO, called BaseM, which works for other lowest-level-monads, too, like 'ST s'. It includes a ChoiceT monad transformer, which is like ListT, but is not broken. Further it has very useful monadic functions. For example there is an 'abort' function to escape from a ContT computation, so you don't need to use that ugly callCC, if you just want early exit route. You also get labelled jumps for free, if you ever need them desperately. As an interesting feature, if you have a monad, which is isomorphic to a known monad, you can derive all the Functor/Monad instance functions from this isomorphism. All you need to do is to tell monadLib how one would turn a computation of the monad in question into a computation of the known monad. 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
[Haskell-cafe] emacs tags
(I asked this question on the logical email list to ask, haskell-mode, but got no reply, so I'm hoping someone here might know the answer.) I tried to use tags with emacs. I ran :etags in ghci, then tried to use C-c M-. inside Emacs to find the definition of a symbol. It reported no source information available. I did some basic checking---a TAGS file does exist in the same directory as the file I was visiting, and contains some kind of entry for the specific symbol (whether the right syntax I don't know). I'm using haskell-mode 2.4 and emacs 21.3.1 on Windows XP. Also ghci 6.12.1. Thanks, Mike ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Canonical Graphviz code
Graphviz (http://graphviz.org/) has the option to convert provided Dot code for visualising a graph into a canonical form. For example, take the sample Dot code: | digraph foo { | a [color=blue]; | subgraph cluster_bar { | a [label=hi!] | b [color=blue, label=bye!]; | b - c; | } | a - b; | a - c; | c - d; | d [color=red] ` Calling dot -Tcanon on this produces: , | digraph foo { | node [label=\N]; | subgraph cluster_bar { | a [label=hi!, color=blue]; | b [label=bye!, color=blue]; | b - c; | a - b; | a - c; | } | d [color=red]; | c - d; | } ` Note in particular the following: * The addition of the top-level node [label=\N] attribute; this happens automatically even if all nodes have their own custom label. * The two `a' nodes are merged into the inner-most cluster/subgraph that they are defined in (since they represent the same node). * The attributes for `b' are re-ordered. * The a - b and a - c edges are shifted into the cluster, since all of the related nodes are in that cluster (note that the `c' node is implicitly defined there since an edge involving it is defined there). * The c - d edge is shifted to being _after_ the definition of the `d' node (in fact, in each grouping all nodes are defined before edges). I've recently thought up a way that I can duplicate this functionality (in terms of what it does, not necessarily the actual output) in my graphviz library (http://hackage.haskell.org/package/graphviz), however I'm not sure how closely to follow what Graphviz does. What would the community prefer out of the following (including a mixture, such as options 2 and 3): 1) Match Graphviz's output as much as possible (note that the ordering of the attributes won't happen this way, since I'll be sorting them alphabetically rather than working out Graphviz's arcane rules). 1a) As with 1), but don't worry about defining extra attributes such as node [label=\N]. 2) Explicitly define nodes that are only mentioned in edges (e.g. actually define a `c' node, even if it doesn't have any extra attributes). Note that this already happens if such an edge is specified inside a different cluster than the already known node is in; in that case then the stand-alone node is defined in the cluster its edge is defined in, and the actual edge is moved into the outer context that combines the two clusters. 2a) As with 2), but define all edges in the overall graph rather than grouping them internally inside clusters, etc. 3) Group common attributes together as much as possible (e.g. inside the bar cluster, define another subgroup which has a top-level attribute node [color=blue] and define the `a' and `b' nodes in there). Not sure how well this will work with edges though, and is probably not possible in conjunction with option 2a). This is a bit tricky and subtle: if `a' and `b' are already in such a subgraph, but an edge specifying one of them is defined _before_ the subgraph is defined, then that node will have an explicit color attribute defined of (i.e. empty string), though I would classify this as a bug. 4) As an alternate to option 3), remove all explicit top-level node and edge attributes and move them all to the affected node and edge definitions themselves; this may require option 2). I'm also willing to hear and consider other possible variants; however, I'm only going to code (at most) one. -- 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] Re: Rewriting a famous library and using the same name: pros and cons
Ivan Lazar Miljenovic wrote: Stephen Tetley stephen.tet...@gmail.com writes: I think it was Hugs compliant as least for some revisions - I seem to remember looking at it before I switched to GHC. People still use Hugs? :p MPJ uses it for teaching Haskell because it's a lot easier to install than GHC. I've heard tale of people using it in the embedded world (again because of easy portability), though I haven't witnessed it to know how recent that is. I do my best to retain compatibility with Hugs for my Hackage libraries, and I use Hugs to define the boundary between semiportable (i.e., not H98 but still portable) vs nonportable (i.e., GHC-only). Doing so has highlighted some simple bugs in Cabal which, AFAIK, haven't been fixed yet. Perhaps because I seem to be the only advocate for trying to keep Hugs support alive, and I don't know the Cabal code well enough to make the fix myself. A bit more seriously: is there any listing anywhere of which extensions Hugs supports? Cabal has a partial listing embedded in its code, though I can't seem to find a textual version at the moment. In general, Hugs has all the features of GHC 6.6: FFI, CPP, MPTCs, FunDeps, OverlappingInstances,... I'm forgetting off-hand whether it has Rank2Types/RankNTypes, but I think so. The one notable difference between Hugs and GHC6.6 is that it does not have IncoherentInstances, and instead supports a different/incompatible way of trying to solve that problem. Of course, since it's GHC6.6-era that means it doesn't support LANGUAGE pragma to enable these features. The -98 flag enables most of the extensions with separate flags for OverlappingInstances, Not-IncoherentInstances, and CPP (or any other preprocessor); and in order to use the FFI you must first run ffihugs in order to compile the bindings. Because the shift from GHC6.6 to GHC6.8 was so significant, it'd be nice if someone put out a maintenance version of Hugs which adds support for LANGUAGE pragma and similar compilation interface issues, even if the underlying code base remains the same. One can dream, eh? Definitely serious: if anything, I would care more about ensuring compatability with JHC, UHC, etc. than Hugs nowadays. Certainly JHC and UHC should be targeted for compatibility. However, doing so seems unlikely to come at the cost of compatibility with Hugs. Hugs implements H98 along with the most venerable and widely used extensions. Consequently, the language Hugs understands happens to be the same one that's the goal of modern Haskell compilers like JHC and UHC. However little maintenance Hugs is getting, it captures all of classic Haskell. The hallmarks of new Haskell like GADTs and type functions are, so far as I'm aware, considered a more distant goal for alternative compilers. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Rewriting a famous library and using the same name: pros and cons
Ivan Lazar Miljenovic wrote: Stephen Tetley stephen.tet...@gmail.com writes: On 3 July 2010 14:00, Ivan Lazar Miljenovic ivan.miljeno...@gmail.com wrote: So this argument isn't valid ;-) I think it was Hugs compliant as least for some revisions - I seem to remember looking at it before I switched to GHC. Actually, how would you call it in Hugs? Just start it explicitly with the -98 flag? For most extensions you use the -98 flag, for OverlappingInstances you use +o, and for CPP you use -F'cpp -P -traditional -D__Hugs__' (or similar). If FFI is required then call the program with ffihugs first. E.g. $ ffihugs -98 +o -F'cpp -P -traditional' Bar.hs $ hugs -98 +o -F'cpp -P -traditional' Bar.hs Hugs does not know about LANGUAGE pragmas, as those were added in GHC 6.8. And Cabal does not infer the need for -98 or +o based on the Extensions: field, so you'll have to add them to Hugs-Options: manually. Also, there are some bugs in Cabal preventing the mixture of CPP and FFI, even though this is fine in Hugs. See http://community.haskell.org/~wren/cabal-ffihugstest for more details. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] More experiments with ATs
Andrew Coppin wrote: Brent Yorgey wrote: On Sun, Jul 04, 2010 at 10:31:34AM +0100, Andrew Coppin wrote: I have literally no idea what a type family is. I understand ATs (I think!), but TFs make no sense to me. ATs are just TFs which happen to be associated with a particular class. So if you understand ATs then you understand TFs too, you just didn't know it. =) How would that make sense though? I'm having trouble forming a mental image of how / why you'd use that... Type families ---in the traditional dependent-types sense, not necessarily the GHC sense--- are a collection of related types which are the same in some sense, but which are distinguished from one another by indices. There are two ways of interpreting this. The first approach is to think about type families where the index gives you some type-level information about the term-level value; this is the same thing as GADTs. That is, if we take the standard whipping boy: data List :: * - * - * where nil :: forall a. List a Z cons :: forall a. a - List a n - List a (S n) then we'll want some way of talking about all Lists, irrespective of their lengths. Thus, List A (for some A) is a type family, but not a type. There's a fundamental difference here between parametric polymorphism and type indices. In Coq it's made more explicit (though it's still rendered subtle), but in Haskell it can be a bit harder to see. The other perspective is to think of type families as a function from indices to types, where the particular function constitutes the type family. This is the approach taken by associated types and type families in GHC. TFs, as separate from ATs, are useful for implementing type-level functions. For example, we could define addition on Z and S, which would allow us to give the type (++) :: List a n - List a m - List a (Plus n m) The type family Plus takes two indices and returns a type, but it does so in a way that it is allowed to perform case analysis on the input arguments--- and therefore is not parametric. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe