Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Quoth Duncan Coutts duncan.cou...@worc.ox.ac.uk: You must not do this. It breaks the semantics of the language. Other people have given practical reasons why you should not but a theoretical reason is that you've defined a non-continuous function. That is impossible in the normal semantics of pure functional languages. So you're breaking a promise which we rely on. Could you elaborate a little, in what sense are we (?) relying on it? I actually can't find any responses that make a case against it on a really practical level - I mean, it seems to be taken for granted that it will work as intended, and we're down to whether we ought to have such intentions, as a matter of principle. If you've identified a problem here with semantics that would break normal evaluation, from the perspective of the programmer's intention, then this would be the first practical reason? Donn It is not safe. It's almost as bad as a function isBottom, which is the canonical non-continuous function. It's defined by: isBottom _|_ = True isBottom _ = False Of course your tryArith only tests for certain kinds of _|_ value, but in principle the problem is the same. It is not safe because it distinguishes values that are not supposed to be distinguishable. This invalidates many properties and transformations. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Donn Cave wrote: Could you elaborate a little, in what sense are we (?) relying on it? I actually can't find any responses that make a case against it on a really practical level - I mean, it seems to be taken for granted that it will work as intended, and we're down to whether we ought to have such intentions, as a matter of principle. If you've identified a problem here with semantics that would break normal evaluation, from the perspective of the programmer's intention, then this would be the first practical reason? Off the top of my head, here is a possible case: foo :: Int - Int foo x = ... -- something that might throw an exception bar :: Int - Blah bar x = ... -- internally use foo and catch the exception baz :: Int - Blah baz = bar . foo In this case, if the foo in baz throws an exception, I think bar may catch it and attempt to handle it as if the foo in bar had thrown it, but we probably would have expected this exception to go all the way to the top level and halt the program since exceptions are usually due to programmer error. But I didn't test this, and since this isn't something I've ever done before I can't be 100% sure of its behavior. - Jake ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Tue, 2009-03-24 at 23:13 -0700, Donn Cave wrote: Quoth Duncan Coutts duncan.cou...@worc.ox.ac.uk: You must not do this. It breaks the semantics of the language. Other people have given practical reasons why you should not but a theoretical reason is that you've defined a non-continuous function. That is impossible in the normal semantics of pure functional languages. So you're breaking a promise which we rely on. Could you elaborate a little, in what sense are we (?) relying on it? I actually can't find any responses that make a case against it on a really practical level - I mean, it seems to be taken for granted that it will work as intended, It shouldn't be. Consider: loop = loop blam = error blam notReallyTry = unsafePerformIO . try . evaluate Now, normally, we have, for all x, y, x `seq` y `seq` x = y `seq` x But we clearly do *not* have this for x = blam, y = loop, since the equality isn't preserved by notReallyTry: notReallyTry $ blam `seq` loop `seq` blam = Left (ErrorCall blam) notReallyTry $ loop `seq` blam= loop Now, say a compiler sees the definition foo x y = x `seq` y `seq` x in one module, and then in a later one expectToBeTotal = notReallyTry $ foo blam loop ? What happens if the compiler, while compiling foo, notices that x is going to be evaluated eventually anyway, and decides against forcing it before y? What if foo was written as foo (!x) (!y) = x ? Which order are the evaluations performed in? In a purely functional language, it doesn't matter; but all of a sudden with impure operations like notReallyTry popping up, it does. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: about Haskell code written to be too smart
Manlio Perillo wrote: Conal Elliott ha scritto: Manlio, We live in the age of participation -- of co-education. Don't worry about text-books. Contribute to some wiki pages blogs today that share these smart techniques with others. When I started learning Haskell (by my initiative), what I did was: [steps 1) - 9), mostly internet tutorials ] I think you'd have had a much easier time by starting with a proper book right away, like Richard Bird's Introduction to Functional Programming in Haskell, accompanied by Real World Haskell. You see, the reason that books cost money is (should be) high quality content. :) Regards, apfelmus -- http://apfelmus.nfshost.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: about Haskell code written to be too smart
Dan Piponi wrote: Miguel Mitrofanov wrote: takeList = evalState . mapM (State . splitAt) However, ironically, I stopped using them for pretty much the same reason that Manlio is saying. Are you saying there's a problem with this implementation? It's the only one I could just read immediately. The trick is to see that evalState and State are just noise for the type inferencer so we just need to think about mapM splitAt. This turns a sequence of integers into a sequence of splitAts, each one chewing on the leftovers of the previous one. *Way* easier than both the zipWith one-liner and the explicit version. It says exactly what it means, almost in English. I couldn't agree more. In other words, splitAt is really to be thought of as a function that lives in the state monad. Regards, apfelmus -- http://apfelmus.nfshost.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Definition of tail recursive wrt Folds
Hi, Just looking at the definitions for foldr and foldl I see that foldl is (apparently) tail recursive while foldr is not. Why? Is it because foldl defers calling itself until last whereas foldr evaluates itself as it runs? What, strictly speaking, is the definition of ”tail recursive” as opposed to just “recursive”? Cheers, Mark Spezzano No virus found in this outgoing message. Checked by AVG. Version: 7.5.557 / Virus Database: 270.11.27/2021 - Release Date: 24/03/2009 4:00 PM ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Definition of tail recursive wrt Folds
wikipedia is your friend... http://en.wikipedia.org/wiki/Fold_(higher-order_function) Tammo 2009/3/25 Mark Spezzano mark.spezz...@chariot.net.au: Hi, Just looking at the definitions for foldr and foldl I see that foldl is (apparently) tail recursive while foldr is not. Why? Is it because foldl defers calling itself until last whereas foldr evaluates itself as it runs? What, strictly speaking, is the definition of ”tail recursive” as opposed to just “recursive”? Cheers, Mark Spezzano No virus found in this outgoing message. Checked by AVG. Version: 7.5.557 / Virus Database: 270.11.27/2021 - Release Date: 24/03/2009 4:00 PM ___ 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] about Haskell code written to be too smart
2009/3/24 Jonathan Cast jonathancc...@fastmail.fm: On Tue, 2009-03-24 at 22:33 +0300, Eugene Kirpichov wrote: Pretty cool once you know what the function does, but I must admit I wouldn't immediately guess the purpose of the function when written in this way. I wouldn't immediately guess the purpose of the function written in any way. I think, in general, the best way to document the purpose of the function is -- | Split a function into a sequence of partitions of specified lenth takeList :: [Int] - [a] - [[a]] Thank-you Jonathan. That's the first message in this thread I've manage to understand. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
What about import Data.List partAt n xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partAt n xs) t = partAt 3 [1..10] It's tail recursive (I think!) and should be pretty easy to understand even for a beginner, no? 2009/3/24 Manlio Perillo manlio_peri...@libero.it: Tim Newsham ha scritto: These friends are very interested in Haskell, but it seems that the main reason why they don't start to seriously learning it, is that when they start reading some code, they feel the Perl syndrome. That is, code written to be too smart, and that end up being totally illegible by Haskell novice. I too have this feeling, from time to time. Since someone is starting to write the Haskell coding style, I really suggest him to take this problem into strong consideration. When you think about it, what you are saying is that Haskell programmers shouldn't take advantage of the extra tools that Haskell provides. No, I'm not saying this. But, as an example, when you read a function like: buildPartitions xs ns = zipWith take ns . init $ scanl (flip drop) xs ns that can be rewritten (argument reversed) as: takeList :: [Int] - [a] - [[a]] takeList [] _ = [] takeList _ [] = [] takeList (n : ns) xs = head : takeList ns tail where (head, tail) = splitAt n xs I think that there is a problem. The buildPartition contains too many blocks. And I have read code with even more blocks in one line. It may not be a problem for a seasoned Haskell programmer, but when you write some code, you should never forget that your code will be read by programmers that can not be at your same level. I think that many Haskell programmers forget this detail, and IMHO this is wrong. Haskell provides the ability to abstract code beyond what many other programming systems allow. This abstraction gives you the ability to express things much more tersely. This makes the code a lot harder to read for people who are not familiar with the abstractions being used. The problem is that I have still problems at reading and understanding code that is too much terse... Because I have to assemble in my mind each block, and if there are too many blocks I have problems. [...] Manlio ___ 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] Are there performant mutable Arrays in Haskell?
To make a long story short, here is the library code: elems arr = case bounds arr of (_l, _u) - [unsafeAt arr i | i - [0 .. numElements arr - 1] And my version: boundedElems arr = case bounds arr of (_l, _u) - [unsafeAt arr i | i - [1737 .. 1752]] Is there a reason, why the library version is 4 times faster, than mine? There shouldn't be any reason. Try putting {-# INLINE boundedElems #-} to make it inline, it might be faster. Ah, ok, did that, but no difference. :) If I got it right, for the library version exists a C-translation while for my version there isn't. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
sorry, wrong function. should be partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) t = partitions [1,2,3] [1..10] which is not quite as nice, I admit. 2009/3/25 Thomas Hartman tphya...@gmail.com: What about import Data.List partAt n xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partAt n xs) t = partAt 3 [1..10] It's tail recursive (I think!) and should be pretty easy to understand even for a beginner, no? 2009/3/24 Manlio Perillo manlio_peri...@libero.it: Tim Newsham ha scritto: These friends are very interested in Haskell, but it seems that the main reason why they don't start to seriously learning it, is that when they start reading some code, they feel the Perl syndrome. That is, code written to be too smart, and that end up being totally illegible by Haskell novice. I too have this feeling, from time to time. Since someone is starting to write the Haskell coding style, I really suggest him to take this problem into strong consideration. When you think about it, what you are saying is that Haskell programmers shouldn't take advantage of the extra tools that Haskell provides. No, I'm not saying this. But, as an example, when you read a function like: buildPartitions xs ns = zipWith take ns . init $ scanl (flip drop) xs ns that can be rewritten (argument reversed) as: takeList :: [Int] - [a] - [[a]] takeList [] _ = [] takeList _ [] = [] takeList (n : ns) xs = head : takeList ns tail where (head, tail) = splitAt n xs I think that there is a problem. The buildPartition contains too many blocks. And I have read code with even more blocks in one line. It may not be a problem for a seasoned Haskell programmer, but when you write some code, you should never forget that your code will be read by programmers that can not be at your same level. I think that many Haskell programmers forget this detail, and IMHO this is wrong. Haskell provides the ability to abstract code beyond what many other programming systems allow. This abstraction gives you the ability to express things much more tersely. This makes the code a lot harder to read for people who are not familiar with the abstractions being used. The problem is that I have still problems at reading and understanding code that is too much terse... Because I have to assemble in my mind each block, and if there are too many blocks I have problems. [...] Manlio ___ 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] The votes are in!
2009/3/24 John Van Enk vane...@gmail.com: If any one seconds the motion, i'm picking up this part of the thread and putting it in the humor section of the haskell wiki. /jve Seconded. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Grouping - Map / Reduce
Dear Günther, the map can't be consumed while it is constructed. At any point during its construction you don't know for any key in the map if it will appear in the not cosumed rest of the list again. This means you can't process any entry of the map because it may change later. The only point when nothing will change anymore is when the map is completely constructed. Regards, Martin. Günther Schmidt schrieb: Hi Ketil, Ketil Malde schrieb: Gü?nther Schmidt gue.schm...@web.de writes: let say I got an unordered lazy list of key/value pairs like [('a', 99), ('x', 42), ('a', 33) ... ] and I need to sum up all the values with the same keys. So far I wrote a naive implementation, using Data.Map, foldl and insertWith. Data.Map.fromListWith (+) The building of this map is of course a bottleneck, the successive processing needs to wait until the entire list is eventually consumed the Map is built and flattened again. Sure this is not an artifact of the laziness of foldl? well I can't really see how the map could be consumed *while* it's still being built, I just don't see it. (I'm using foldl' and insertWith', sry for not saying so initially). Is there another way of doing this, something more streaming architecture like? I don't see how you can do this much better - for a small, fixed set of keys, you could use an (STU) array for the sums, but it depends if the added complexity is worth it. You're already doing a single pass over the data. -k ___ 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] STM orElse semantics
I'm not 100% clear on the behaviour of the STM function orElse. The documentation says: Compose two alternative STM actions (GHC only). If the first action completes without retrying then it forms the result of the orElse. Otherwise, if the first action retries, then the second action is tried in its place. If both actions retry then the orElse as a whole retries. What is the definition of retrying in If the first action completes without retrying then... -- does it mean only explicitly retrying via the retry function, or does it include a retry caused by a write conflict at commit time of the first action? That is, if the first action could complete, but doesn't simply due to interference from another transaction, does orElse run the second action, or rerun the first? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] STM orElse semantics
Compose two alternative STM actions (GHC only). If the first action completes without retrying then it forms the result of the orElse. Otherwise, if the first action retries, then the second action is tried in its place. If both actions retry then the orElse as a whole retries. What is the definition of retrying in If the first action completes without retrying then... -- does it mean only explicitly retrying via the retry function, or does it include a retry caused by a write conflict at commit time of the first action? I'm quite sure orElse only concerns explicit retries, it wouldn't make much sense otherwise. Cheers, Peter ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Jonathan Cast jonathancc...@fastmail.fm writes: On Tue, 2009-03-24 at 23:13 -0700, Donn Cave wrote: Quoth Duncan Coutts duncan.cou...@worc.ox.ac.uk: You must not do this. It breaks the semantics of the language. Other people have given practical reasons why you should not but a theoretical reason is that you've defined a non-continuous function. That is impossible in the normal semantics of pure functional languages. So you're breaking a promise which we rely on. Could you elaborate a little, in what sense are we (?) relying on it? I actually can't find any responses that make a case against it on a really practical level - I mean, it seems to be taken for granted that it will work as intended, It shouldn't be. Consider: loop = loop blam = error blam notReallyTry = unsafePerformIO . try . evaluate Now, normally, we have, for all x, y, x `seq` y `seq` x = y `seq` x But we clearly do *not* have this for x = blam, y = loop, since the equality isn't preserved by notReallyTry: notReallyTry $ blam `seq` loop `seq` blam = Left (ErrorCall blam) notReallyTry $ loop `seq` blam= loop Now, say a compiler sees the definition foo x y = x `seq` y `seq` x in one module, and then in a later one expectToBeTotal = notReallyTry $ foo blam loop ? What happens if the compiler, while compiling foo, notices that x is going to be evaluated eventually anyway, and decides against forcing it before y? What if foo was written as foo (!x) (!y) = x ? Which order are the evaluations performed in? In a purely functional language, it doesn't matter; but all of a sudden with impure operations like notReallyTry popping up, it does. Could you elaborate more about why this kind of breakage wouldn't happen if 'try' is used in an IO monad as intended? Thanks. -- c/*__o/* \ * (__ */\ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Some examples of what might happen: If you have more than one possible exception in your code, you don't know which one you will get. It can vary between compilers, optimization levels, program runs, or even evaluating the same expression within one program. If you have code that have both an infinite loop and an exception you don't know if you'll get the loop or the exception. Breaking the deterministic behaviour can lead to strange consequences, because the compiler relies on it. For instance, the following code let x = someExpression print x print x could print different values for x the two times you print it. (This is somewhat unlikely, but could happen when evaluating in parallel with ghc, because there is a small window where two threads might start evaluating x and later update x with two different values.) -- Lennart On Wed, Mar 25, 2009 at 11:39 AM, Xiao-Yong Jin xj2...@columbia.edu wrote: Jonathan Cast jonathancc...@fastmail.fm writes: On Tue, 2009-03-24 at 23:13 -0700, Donn Cave wrote: Quoth Duncan Coutts duncan.cou...@worc.ox.ac.uk: You must not do this. It breaks the semantics of the language. Other people have given practical reasons why you should not but a theoretical reason is that you've defined a non-continuous function. That is impossible in the normal semantics of pure functional languages. So you're breaking a promise which we rely on. Could you elaborate a little, in what sense are we (?) relying on it? I actually can't find any responses that make a case against it on a really practical level - I mean, it seems to be taken for granted that it will work as intended, It shouldn't be. Consider: loop = loop blam = error blam notReallyTry = unsafePerformIO . try . evaluate Now, normally, we have, for all x, y, x `seq` y `seq` x = y `seq` x But we clearly do *not* have this for x = blam, y = loop, since the equality isn't preserved by notReallyTry: notReallyTry $ blam `seq` loop `seq` blam = Left (ErrorCall blam) notReallyTry $ loop `seq` blam = loop Now, say a compiler sees the definition foo x y = x `seq` y `seq` x in one module, and then in a later one expectToBeTotal = notReallyTry $ foo blam loop ? What happens if the compiler, while compiling foo, notices that x is going to be evaluated eventually anyway, and decides against forcing it before y? What if foo was written as foo (!x) (!y) = x ? Which order are the evaluations performed in? In a purely functional language, it doesn't matter; but all of a sudden with impure operations like notReallyTry popping up, it does. Could you elaborate more about why this kind of breakage wouldn't happen if 'try' is used in an IO monad as intended? Thanks. -- c/* __o/* \ * (__ */\ ___ 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: Exception handling in numeric computations
Jake McArthur j...@pikewerks.com writes: Xiao-Yong Jin wrote: | The problem is that there will be many functions using such | a function to invert a matrix, making this inversion | function return Either/Maybe or packing it in a monad is | just a big headache. I disagree. If you try to take the inverse of a noninvertable matrix, this is an *error* in your code. Catching an error you created in pure code and patching it with chewing gum it is just a hack. A monadic approach (I'm putting Either/Maybe under the same umbrella for brevity) is the only solution that makes any sense to me, and I don't think it's ugly as you are making it out to be. Then, why is 'div' not of type 'a - a - ArithExceptionMonad a' ? Why does it throws this /ugly/ /error/ when it is applied to 0? Why is it not using some beautiful 'ArithExceptinoMonad'? Is 'Control.Exception' just pure /ugly/ and doesn't make any sense? | It is impractical to use method (a), | because not every function that uses 'invMat' knows how to | deal with 'invMat' not giving an answer. So we need to use | method (b), to use monad to parse our matrix around. | | invMat :: Matrix - NumericCancerMonad Matrix | | It hides the exceptional nature of numerical computations | very well, but it is cancer in the code. Whenever any | function wants to use invMat, it is mutated. This is just | madness. You don't want to make all the code to be monadic | just because of singularities in numeric calculation. For functions that don't know or don't care about failure, just use fmap or one of its synonyms. ~ scalarMult 2 $ invMat x See? The scalarMult function is pure, as it should be. There is no madness here. Of course, 'scalarMult' is invulnerable and free of monad. But take a look at the following functions, f1 = scalarMult 2 . invMat f2 l r = l `multMat` invMat r ff :: Matrix - Matrix - YetAnotherBiggerMonad Matrix ff x y = do let ff' = f1 x + f2 y put . (addMat ff') . f1 get tell $ f2 ff' when (matrixWeDontLike (f1 ff') $ throwError MatrixWeDontLike return $ scalarMult (1/2) ff' Yes, I know, it's not really complicate to rewrite the above code. But, what do I really gain from this rewrite? Apologies if this discussion has moved on, but I wanted to comment on this. You gain correctness. Any functions that need to be rewritten in this case should be rewritten anyway, because they're already wrong. Your function ff can fail for certain inputs. This statement: | It is impractical to use method (a), | because not every function that uses 'invMat' knows how to | deal with 'invMat' not giving an answer. So we need to use | method (b), to use monad to parse our matrix around. is conceptually wrong. What does it mean to multiply the inverse of a non-invertible matrix by a scalar? Obviously this is nonsensical. If a computation can fail (as this can), the type of the function should reflect it. The above functions f1 = scalarMult 2 . invMat f2 l r = l `multMat` invMat r should be f1 :: Matrix - Maybe Matrix f1 = fmap (scalarMult 2) . invMat f2 :: Matrix - Matrix - Maybe Matrix f2 l r = fmap (multMat l) $ invMat r Of course these could be written with Control.Applicative as well: f1 m = scalarMult 2 $ invMat m f2 l r = multMat l $ invMat r ff :: Matrix - Matrix - YetAnotherBiggerMonad Matrix ff x y = let ff' = f1 x + f2 y ... in scalarMult (1/2) ff' (I think you may be missing an argument to f2 here.) This computation can fail as well, if the constituent parts fail. The separate parts can be combined with applicative style: ff :: Matrix - Matrix - Maybe Matrix ff x y = scalarMult (1/2) $ ( (+) $ f1 x * f2 y) Compare this to the same code using monadic Maybe: ff :: Matrix - Matrix - Maybe Matrix ff x y = do x' - f1 x y' - f2 y scalarMult (1/2) $ x' + y' You gain clarity and brevity. Both examples are shorter and easier to understand because you aren't messing with all the plumbing of error handling using exceptions, although I find the Applicative version especially clear. If you would like to keep track of why a computation failed, then use Either instead of Maybe with the Left carrying a reason for failure (e.g. NonInvertibleMatrix) Finally, you gain safety. When you use a function f1 :: Matrix - Matrix, you can be assured that you will get an actual, meaningful answer. If you use a function f2 :: Matrix - Maybe Matrix, you know that you may not get a meaningful answer, and it is simple to handle at the appropriate level of your code. I (and many other Haskell users) find this to be conceptually cleaner than throwing dynamic exceptions or using undefined. Incidentally, this is one reason why many experienced Haskellers like the applicative style. It allows you to express your computations without obtrusive error handling mixed in. It's also more general than monads, so can be applied in
[Haskell-cafe] Re: generalized shuffle
o...@okmij.org ha scritto: Hello! The reason is that in a project I need to extract random elements from a list (and I need to extract a lot of them), and using normal methods [1] seems to be rather inefficient. Note that I have used an incorrect term, sorry. What I need, in detail, is to: Given a population of 100480507 elements, extract 17770 random samples, where each sample has a size between 1 and 480189. Yes, it is again my Netflix Prize project; here I'm trying to write a program to generate the entire training data set using random data. [1] by normal method I mean: extract a random number, in the range [0, n] (where n is the length of the sequence), and get the element indexed by that number. BTW, have you tried to use Data.IntMap? That is, put the sequence into an IntMap (each element being indexed by its index) and then extract elements at random; IntMap seems to be quite efficient... This should be ok if I need independent random choices from a population, but I need random samples, instead, sorry for the confusion. Do you think that it is possible to further optimize your tree structure? Or to use IntMap, instead? Cheers, Oleg Thanks Manlio ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
Heinrich Apfelmus ha scritto: Manlio Perillo wrote: Conal Elliott ha scritto: Manlio, We live in the age of participation -- of co-education. Don't worry about text-books. Contribute to some wiki pages blogs today that share these smart techniques with others. When I started learning Haskell (by my initiative), what I did was: [steps 1) - 9), mostly internet tutorials ] I think you'd have had a much easier time by starting with a proper book right away, like Richard Bird's Introduction to Functional Programming in Haskell, accompanied by Real World Haskell. Unfortunately, one year ago Real World Haskell was not here. And note that I have no problems with basic functional programming concepts. My problems are specific to Haskell. You see, the reason that books cost money is (should be) high quality content. :) Manlio ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: about Haskell code written to be too smart
Alberto G. Corona agocor...@gmail.com wrote: However, reusability of source code and maintainability has never been taken seriously by haskell programmers, simply because there are no industrial projects in Haskell with dozens of people with different skills that come and go. Now that's a claim. In the sense that I don't do commercial haskell coding, but know what maintainability is, anyway: I've maintained everything from utterly atrocious to mindboggingly elegant java code for a living. I can tell you with 110% confidence that maintainability is about composibility, _on_every_level_: Not just on statement-level. Otherwise, I wouldn't have cussed that much. Curiously enough, as soon as the code didn't make you whince, it was easily maintainable. This is closely related to Linus' observation that good [imperative] code is data-structure centred, and Greenspun's Tenth Rule. With Haskell, there's finally a language that makes large-scale changes as easy as small-scale changes without having to resort to implement an interpreter for a functional language. As the position of changes tends to travel upwards in a bottom-up approach and small-scale changes are easy to pull off (you already understand what you need to do since otherwise you wouldn't have identified the need for a small-scale change and continued to add onion layers), caring about editability on function level just doesn't pay off. That's why I don't care whether or not I have to re-write a whole function to change it: If it's going to change, which isn't all that likely, I can cope with renaming it and write another say 160 characters directly below it. Adding a proper quickcheck property (if it didn't exist, yet, or the semantics changed) is usually more work: You don't only need to get the preposition right, but also the test case generator. -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
wren ng thornton ha scritto: Manlio Perillo wrote: [...] Following directly from the Rule of Least Power, if you can get away with foreach then that's what you should use. Why? Because the less power the construct has, the fewer corner cases and generalizations a reader of the code needs to consider. Now, just because iterators exist does not mean that one should never use the more general tool. If you're fighting to break out of your chosen straitjacket, then chances are it's the wrong one to use in the first place; it'd be clearer to use more power and have less fighting. [...] Note that, as I have already written, I agree with you. And this is one of the reasons i like Haskell. The main problem, here, is that: - recursion and pattern matching are explained in every tutorial about functional programming and Haskell. This is the reason why I find them more natural. - high level, Haskell specific, abstractions, are *not* explained in normal tutorials or books. The libraries where these concepts are implemented, are not well documented. Most of the documentation is in research papers, and a normal programmer don't want to read these papers. Only in the recent Real World Haskell, all these high level abstraction have been properly documented Manlio ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
The beauty of functional programming is that there doesn't have to be a conflict between those who prefer explicit and those who prefer implicit recursion. Think of them as different views on the same functions - just as with graphical visualizations, pick the view best suited to your purpose and use equational reasoning to transform one view into another, as needed. Improving your experience in reasoning about code is going to help at every level of abstraction, and since you've already paid the price (using a pure language, to make reasoning easier) you might as well avail yourself of the facilities;-) While developing, I might prefer abstraction, as fewer details mean that I can hold more of the problem in my head at any point, increasing my chances of seeing all the way to a solution; if optimizing, or when I haven't found the right abstractions yet, I might have to resort to less abstract code until I've sorted out those details or until GHC deals with the more abstract forms as well as with the less abstract ones. Fine, you say, but I'd never would have thought of abstract views like splitAt as a state transformer. Okay, before this thread, I might not have thought of using that, either. But after this thread, I'd hope for it to become part of my thinking about Haskell code. And the way I do that is by taking the abstract code and unfold it (replacing instances of left-hand sides with instances of right-hand sides of definitions - the source links in the Haddock documentation are very useful for that) until I get to some less abstract code that I might have come up with. That doesn't mean that I'd have had the insights to play the derivation backwards, but by breaking the transformation from less abstract to more abstract view into smaller steps, starting from the abstract form that incorporates the additional insights I was missing, I can increase my understanding of what is going on, and my chances of noticing the opportunities next time. It also confirms whether or not the two solutions really are the same (as has been pointed out, that wasn't the case here). Paraphrasing and tweaking Sjur Gjøstein Karevoll's remark a little: clever Perl code is what you hope you understood in the past, when you wrote it; clever Haskell code is what you hope you'll understand in the future, when you'll write it yourself!-) The derivation below is best followed by replaying it yourself in your editor, but I hope you'll find it helpful anyway. Claus -- view transformation: reducing the level of abstraction -- by turning implicit to explict recursion takeList = evalState . mapM (State . splitAt) -- unfold 'mapM' takeList = evalState . sequence . map (State . splitAt) -- unfold 'sequence' takeList = evalState . foldr k (return []) . map (State . splitAt) where k m m' = do x-m; xs-m'; return (x:xs) foldr op n []= n foldr op n (h:t) = h `op` foldr op n t -- specialize 'foldr' for the call paramenters 'k' and 'return []' takeList = evalState . foldrkn . map (State . splitAt) where k m m' = do x-m; xs-m'; return (x:xs) foldrkn []= return [] foldrkn (h:t) = h `k` foldrkn t -- unfold 'k' takeList = evalState . foldrkn . map (State . splitAt) where foldrkn []= return [] foldrkn (h:t) = do x-h; xs-foldrkn t; return (x:xs) -- foldr op n . map f = foldr (op.f) n takeList = evalState . foldrkn where foldrkn []= return [] foldrkn (h:t) = do x-State (splitAt h); xs-foldrkn t; return (x:xs) -- unfold 'return' for 'State', eta-expand 'splitAt h' takeList = evalState . foldrkn where foldrkn []= State (\s-([],s)) foldrkn (h:t) = do x-State (\s-splitAt h s); xs-foldrkn t; State (\s-(x:xs,s)) -- eta-expand body of 'takeList' takeList ns xs = evalState (foldrkn ns) xs where foldrkn []= State (\s-([],s)) foldrkn (h:t) = do x-State (\s-splitAt h s); xs-foldrkn t; State (\s-(x:xs,s)) -- unfold the second '=' for 'State' takeList ns xs = evalState (foldrkn ns) xs where foldrkn []= State (\s-([],s)) foldrkn (h:t) = do x-State (\s-splitAt h s) State (\s-let (xs,s') = runState (foldrkn t) s in runState (State (\s-(x:xs,s))) s') -- runState . State = id takeList ns xs = evalState (foldrkn ns) xs where foldrkn []= State (\s-([],s)) foldrkn (h:t) = do x-State (\s-splitAt h s) State (\s-let (xs,s') = runState (foldrkn t) s in (\s-(x:xs,s)) s') -- beta-reduce takeList ns xs = evalState (foldrkn ns) xs where foldrkn []= State (\s-([],s)) foldrkn (h:t) = do x-State (\s-splitAt h s) State (\s-let (xs,s') = runState (foldrkn t) s in (x:xs,s')) -- unfold the remainign '=' for 'State' takeList ns xs = evalState (foldrkn ns) xs where foldrkn []= State (\s-([],s)) foldrkn (h:t) = State (\s-let (x,s') =
Re: [Haskell-cafe] about Haskell code written to be too smart
On Tue, Mar 24, 2009 at 10:32 PM, wren ng thornton w...@freegeek.orgwrote: Both of these conclusions seem quite natural to me, even from before learning Haskell. It seems, therefore, that naturality is not the proper metric to discuss. It's oft overlooked, but the fact is that expressivity comes not from more formal power, but from _less_. * Natural language has a limited range of words and syntactic constructs, but gives the larger-enough building blocks to enable unconstrained communication; whereas a language with a unique word for every utterance (arguably simpler) is impossible to learn. On the other hand, -certain- languages are more expressive than others. As an example, I personally find English far more expressive than both Vietnamese and Japanese, yet English is far more complicated. Japanese, for example, has exactly 1 pronunciation for each alphabet letter. Hence you'll never find words in English like lead and lead, where the first means to guide someone or something, or to give direction, and the second is a chemical element. Words that are spelled the same in Japanese are pronounced the same 100% of the time. Furthermore, I find that you are far more limited in your choices of how to form ideas into sentences. In English there might be 20 different ways to phrase the exact same sentence for use in a certain context, where the sentences end up being almost identical with the exception of 1 or 2 words changed or shuffled around. In Japanese there would probably be far fewer. In Vietnamese there's a similar problem, in that there are not very many synonyms at all, and NO conjugations. It is complicated by the fact that it's a tonal language, but on the other hand the tonality independent of the expressivity in my experience. Similar to Chinese, although I can't speak for the expressivity of Chinese I would not be surprised at all if written Chinese was extremely expressive, but spoken not so much. Anyway the point of all this is that in English you have more freedom and more power, and hence you use (abuse?) the syntax of the language to create words, sentences, and phrases that express very powerful things. Furthermore, they are things that almost all English speakers would be able to grasp the full meaning of what you've said. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Haddock GSoC project
I'm interested in being a GSoC student, and the Haddock-related tickets looked like a good place to start http://hackage.haskell.org/trac/summer-of-code/ticket/1567 http://hackage.haskell.org/trac/summer-of-code/ticket/1568 http://hackage.haskell.org/trac/summer-of-code/ticket/1569 ... haddock could use some love! And I love documentation. I think I'd start by hacking on some relatively easy Haddock tickets to find my way around the code and the hacking process. Then it might be time to move into one of the bigger projects (I'm tempted to say #1567, Haddock: allow documentation to propagate between packages), depending on priorities; probably still working on some smaller but important Haddock tickets. Then it depends how much time we have left in the summer, there's a lot that can be done! - I've hacked on the GHC lexing/parsing code a bit, and I know darcs, haskell, etc., and I've been around watching on mailing-lists since before Haddock 2.x, so I feel like I have a fair amount of context with which to approach this project. What do you think, is this a good project to look towards? What's the next step... should I elaborate my proposal by looking at Haddock tickets and their priorities? But I should have your feedback first; what do the mentors, or the Haskell community, want most to be improved about Haddock? -Isaac ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Definition of tail recursive wrt Folds
On Wed, Mar 25, 2009 at 05:54:17PM +1030, Mark Spezzano wrote: What, strictly speaking, is the definition of ”tail recursive” as opposed to just “recursive”? A recursive function is tail recursive if the final result of the recursive call is the final result of the function itself. If the result of the recursive call must be further processed (say, by adding 1 to it, or consing another element onto the beginning of it), it is not tail recursive. With that said, tail recursion is not that useful of a concept in a lazy language like Haskell. The important concept to know in Haskell is 'guarded recursion', where any recursive calls occur within a data constructor (such as foldr, where the recursive call to foldr occurs as an argument to (:)). This allows the result of the function to be consumed lazily, since it can be evaluated up to the data constructor and the recursive call delayed until needed. -Brent ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Haddock GSoC project
Having cross-package links would be pure awesome. On Wed, Mar 25, 2009 at 10:04 AM, Isaac Dupree m...@isaac.cedarswampstudios.org wrote: I'm interested in being a GSoC student, and the Haddock-related tickets looked like a good place to start http://hackage.haskell.org/trac/summer-of-code/ticket/1567 http://hackage.haskell.org/trac/summer-of-code/ticket/1568 http://hackage.haskell.org/trac/summer-of-code/ticket/1569 ... haddock could use some love! And I love documentation. I think I'd start by hacking on some relatively easy Haddock tickets to find my way around the code and the hacking process. Then it might be time to move into one of the bigger projects (I'm tempted to say #1567, Haddock: allow documentation to propagate between packages), depending on priorities; probably still working on some smaller but important Haddock tickets. Then it depends how much time we have left in the summer, there's a lot that can be done! - I've hacked on the GHC lexing/parsing code a bit, and I know darcs, haskell, etc., and I've been around watching on mailing-lists since before Haddock 2.x, so I feel like I have a fair amount of context with which to approach this project. What do you think, is this a good project to look towards? What's the next step... should I elaborate my proposal by looking at Haddock tickets and their priorities? But I should have your feedback first; what do the mentors, or the Haskell community, want most to be improved about Haddock? -Isaac ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe -- /jve ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] a cabal package with both a library and executable programs
Hi. This example is taken from the Cabal documentation: Name:TestPackage ... Library Build-Depends: HUnit Exposed-Modules: A, B, C Executable program1 Main-Is: Main.hs Hs-Source-Dirs: prog1 Other-Modules: A, B Executable program2 Main-Is: Main.hs Hs-Source-Dirs: prog2 Other-Modules: A, C, Utils Here I see a small problem. Why should I explicitly declare modules from the library that are used in the executables? I would like to do, instead ... Executable program1 Main-Is: Main.hs Hs-Source-Dirs: prog1 build-depends: TestPackage Executable program2 Main-Is: Main.hs Hs-Source-Dirs: prog2 build-depends: TestPackag Other-Modules: Utils I tried this, but configuration fails, since Cabal does not find the TestPackage. It is true that it does not yet exists, but we are going to build it! Should I fill a feature request ticket, or this is how it is supposed to work? Thanks Manlio ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: a cabal package with both a library and executable programs
Manlio Perillo manlio_peri...@libero.it wrote: Should I fill a feature request ticket, or this is how it is supposed to work? I would like to be able to do that, too. I also don't want cabal to recompile a thousand modules just for a demo program, and don't want to see hackage being polluted by thousands of foo-lib and foo-bin packages to circumvent the current behaviour, either. That is, feel yourself seconded. -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Exception handling in numeric computations
John Lato jwl...@gmail.com writes: Yes, I know, it's not really complicate to rewrite the above code. But, what do I really gain from this rewrite? Apologies if this discussion has moved on, but I wanted to comment on this. Thanks for elaborating it more. You gain correctness. Any functions that need to be rewritten in this case should be rewritten anyway, because they're already wrong. Your function ff can fail for certain inputs. This statement: | It is impractical to use method (a), | because not every function that uses 'invMat' knows how to | deal with 'invMat' not giving an answer. So we need to use | method (b), to use monad to parse our matrix around. is conceptually wrong. What does it mean to multiply the inverse of a non-invertible matrix by a scalar? Obviously this is nonsensical. If a computation can fail (as this can), the type of the function should reflect it. The above functions f1 = scalarMult 2 . invMat f2 l r = l `multMat` invMat r should be f1 :: Matrix - Maybe Matrix f1 = fmap (scalarMult 2) . invMat f2 :: Matrix - Matrix - Maybe Matrix f2 l r = fmap (multMat l) $ invMat r Of course these could be written with Control.Applicative as well: f1 m = scalarMult 2 $ invMat m f2 l r = multMat l $ invMat r ff :: Matrix - Matrix - YetAnotherBiggerMonad Matrix ff x y = let ff' = f1 x + f2 y ... in scalarMult (1/2) ff' (I think you may be missing an argument to f2 here.) This computation can fail as well, if the constituent parts fail. The separate parts can be combined with applicative style: ff :: Matrix - Matrix - Maybe Matrix ff x y = scalarMult (1/2) $ ( (+) $ f1 x * f2 y) Compare this to the same code using monadic Maybe: ff :: Matrix - Matrix - Maybe Matrix ff x y = do x' - f1 x y' - f2 y scalarMult (1/2) $ x' + y' You gain clarity and brevity. Both examples are shorter and easier to understand because you aren't messing with all the plumbing of error handling using exceptions, although I find the Applicative version especially clear. If you would like to keep track of why a computation failed, then use Either instead of Maybe with the Left carrying a reason for failure (e.g. NonInvertibleMatrix) Finally, you gain safety. When you use a function f1 :: Matrix - Matrix, you can be assured that you will get an actual, meaningful answer. If you use a function f2 :: Matrix - Maybe Matrix, you know that you may not get a meaningful answer, and it is simple to handle at the appropriate level of your code. I (and many other Haskell users) find this to be conceptually cleaner than throwing dynamic exceptions or using undefined. Incidentally, this is one reason why many experienced Haskellers like the applicative style. It allows you to express your computations without obtrusive error handling mixed in. It's also more general than monads, so can be applied in more instances. div (and other non-total functions in the Prelude like head), are also frequently considered ugly hacks. Just because we're stuck with something from H98 doesn't mean that it's necessarily good or elegant (the fail monad method and Functor not being a superclass of Monad come to mind). In some ways FP has moved on since Haskell was formalized. There is an alternative approach that I believe was suggested by somebody else on the list: newtype InvMatrix = Invert {unWrap :: Matrix} then you can do invertMatrix :: Matrix - Maybe InvMatrix invertMatrix = fmap Invert . invMat If you put these in a separate module and export InvMatrix, unwrap, and invertMatrix, but not Invert, then the only way to create an InvMatrix is with invertMatrix, so any data of type InvMatrix is guaranteed to be invertible (and inverted from what you used to create it). Then your ff function becomes: ff :: InvMatrix - InvMatrix - Matrix the final value of the function could be InvMatrix if you can prove that it's invertible after your operations (although to be efficient, this would require exporting the Invert constructor and a proof from the programmer). This keeps ff pure; you don't even have to deal with Maybe (although there are other ramifications to doing this that should be considered). John -- c/*__o/* \ * (__ */\ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: about Haskell code written to be too smart
Manlio Perillo manlio_peri...@libero.it wrote: The main problem, here, is that: - recursion and pattern matching are explained in every tutorial about functional programming and Haskell. This is the reason why I find them more natural. Well, you're going to have a hard time writing a BASIC tutorial without mentioning GOTO. While surely it has to be there, for the sake of completeness of fundamentals, I completely agree that... - high level, Haskell specific, abstractions, are *not* explained in normal tutorials or books. The libraries where these concepts are implemented, are not well documented. Most of the documentation is in research papers, and a normal programmer don't want to read these papers. Only in the recent Real World Haskell, all these high level abstraction have been properly documented ...GOTO alone doesn't teach you how to write a loop, trust me, I was stuck there for a good while, eons ago. The prelude, as well as commonly used functions that should be in there, utterly lack accompanying documentation. There should be no function without a usage, as in foldl/sum/product, and no usage without explanation why foldl is chosen over foldl' and foldr. Think of a Preludopedia, accompanying the Typeclassopedia: Documentation where you don't have to snatch understanding out of assem^H^H^H^H^H^H code written using primitive recursion, to make it a bit easier to see the wood despite of all those trees. PS: Shouldn't zipWith be defined in terms of zip, uncurry and map instead of zipWith f (a:as) (b:bs) = f a b : zipWith f as bs zipWith _ _ _ = [] ? -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haddock GSoC project
Simon Marlow wrote: Obviously I think these tickets are important, since I wrote them :-) In terms of priority, I think #1567 is at the top: not having this harms our ability to reorganise and abstract things, it puts an arbitrary barrier between packages. It's possible my perspective is slightly skewed though, since most of the packages that are affected by this are in GHC's core package collection. still, -reorganization happens in others' packages too, and we want to encourage this! -everyone uses GHC's core packages and complains when the documentation is broken (and unfixable!) :-) but sure, we should find out if other people have higher priorities elsewhere. (cafe citizens and hackers, tell us what you think!) #1568 is just refactoring, but it's a high priority: we need to get this code out of GHC and back into Haddock. This is important for Haddock's long term future and general maintainability, though it won't have any visible effect on the way Haddock works. yes, I agree, things will keep being a little unpleasant until we do this. My intuition says that with 2-3 months I should have time to do this refactoring too, but then, I haven't actually spent a week figuring out just how difficult it is :-). Probably needs some refactoring the data-types that GHC emits comments as, and then possibly-more-complicated having Haddock parse and structure the Haddock-syntax within the comments (and as it relates to the actual code!) The index page really isn't working right now, since we added the search-box functionality it has become unusable for the GHC library docs (small libraries are ok). Thank goodness we have Hoogle and Hayoo. We should really just revert to the old A-Z links, I'm not sure if there's a Haddock ticket for this. maybe http://trac.haskell.org/haddock/ticket/70 is related? There's lot of other stuff that could be done. For instance I'd really like someone with some CSS expertise to have another go at Haddock's HTML layout. I've done some manual HTML/CSS on my own website (W3C validated!)... don't know if it comes anywhere near expertise though :-) One random haddock problem I remember bothering me recently is: no view source link on each instance in the list of instances for a data-type (so I clicked a nearby view source and scrolled to find the instance source, which was in the same module) -Isaac ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Haddock GSoC project
Isaac Dupree wrote: I'm interested in being a GSoC student, and the Haddock-related tickets looked like a good place to start http://hackage.haskell.org/trac/summer-of-code/ticket/1567 http://hackage.haskell.org/trac/summer-of-code/ticket/1568 http://hackage.haskell.org/trac/summer-of-code/ticket/1569 haddock could use some love! And I love documentation. I think I'd start by hacking on some relatively easy Haddock tickets to find my way around the code and the hacking process. Then it might be time to move into one of the bigger projects (I'm tempted to say #1567, Haddock: allow documentation to propagate between packages), depending on priorities; probably still working on some smaller but important Haddock tickets. Then it depends how much time we have left in the summer, there's a lot that can be done! - I've hacked on the GHC lexing/parsing code a bit, and I know darcs, haskell, etc., and I've been around watching on mailing-lists since before Haddock 2.x, so I feel like I have a fair amount of context with which to approach this project. What do you think, is this a good project to look towards? What's the next step... should I elaborate my proposal by looking at Haddock tickets and their priorities? But I should have your feedback first; what do the mentors, or the Haskell community, want most to be improved about Haddock? Obviously I think these tickets are important, since I wrote them :-) In terms of priority, I think #1567 is at the top: not having this harms our ability to reorganise and abstract things, it puts an arbitrary barrier between packages. It's possible my perspective is slightly skewed though, since most of the packages that are affected by this are in GHC's core package collection. #1568 is just refactoring, but it's a high priority: we need to get this code out of GHC and back into Haddock. This is important for Haddock's long term future and general maintainability, though it won't have any visible effect on the way Haddock works. The index page really isn't working right now, since we added the search-box functionality it has become unusable for the GHC library docs (small libraries are ok). Thank goodness we have Hoogle and Hayoo. We should really just revert to the old A-Z links, I'm not sure if there's a Haddock ticket for this. There's lot of other stuff that could be done. For instance I'd really like someone with some CSS expertise to have another go at Haddock's HTML layout. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: about Haskell code written to be too smart
Dan Piponi wrote: Miguel Mitrofanov wrote: takeList = evalState . mapM (State . splitAt) However, ironically, I stopped using them for pretty much the same reason that Manlio is saying. Are you saying there's a problem with this implementation? It's the only one I could just read immediately. The trick is to see that evalState and State are just noise for the type inferencer so we just need to think about mapM splitAt. This turns a sequence of integers into a sequence of splitAts, each one chewing on the leftovers of the previous one. *Way* easier than both the zipWith one-liner and the explicit version. It says exactly what it means, almost in English. But it only works out nicely because the ordering of the components of the pair returned by splitAt matches the ordering that the state monad expects (and I can never remember which way around they are in Control.Monad.State). Try doing it with mapAccumL, which is arguably the right abstraction, but has the components the other way around. Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Wed, 2009-03-25 at 07:39 -0400, Xiao-Yong Jin wrote: Jonathan Cast jonathancc...@fastmail.fm writes: On Tue, 2009-03-24 at 23:13 -0700, Donn Cave wrote: Quoth Duncan Coutts duncan.cou...@worc.ox.ac.uk: You must not do this. It breaks the semantics of the language. Other people have given practical reasons why you should not but a theoretical reason is that you've defined a non-continuous function. That is impossible in the normal semantics of pure functional languages. So you're breaking a promise which we rely on. Could you elaborate a little, in what sense are we (?) relying on it? I actually can't find any responses that make a case against it on a really practical level - I mean, it seems to be taken for granted that it will work as intended, It shouldn't be. Consider: loop = loop blam = error blam notReallyTry = unsafePerformIO . try . evaluate Now, normally, we have, for all x, y, x `seq` y `seq` x = y `seq` x But we clearly do *not* have this for x = blam, y = loop, since the equality isn't preserved by notReallyTry: notReallyTry $ blam `seq` loop `seq` blam = Left (ErrorCall blam) notReallyTry $ loop `seq` blam= loop Now, say a compiler sees the definition foo x y = x `seq` y `seq` x in one module, and then in a later one expectToBeTotal = notReallyTry $ foo blam loop ? What happens if the compiler, while compiling foo, notices that x is going to be evaluated eventually anyway, and decides against forcing it before y? What if foo was written as foo (!x) (!y) = x ? Which order are the evaluations performed in? In a purely functional language, it doesn't matter; but all of a sudden with impure operations like notReallyTry popping up, it does. Could you elaborate more about why this kind of breakage wouldn't happen if 'try' is used in an IO monad as intended? It would. But it would happen in IO, which is allowed to be non-deterministic. Pure Haskell is not allowed to be non-deterministic. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
On Wed, 2009-03-25 at 15:09 +, Simon Marlow wrote: the ordering that the state monad expects (and I can never remember which way around they are in Control.Monad.State). Really? I found it obvious once I figured out it how simple it made (=). With the order from Control.Monad.State (with constructors ignored): a = f = \ s - case s a of (x, s') - f x s' Reversing the order of the components of the result gives you a = f = \ s - case s a of (s', x) - f x s' which just looks weird. Try doing it with mapAccumL, which is arguably the right abstraction, but has the components the other way around. Define swap (a, b) = (b, a) You'll never worry about the order of components of a pair again. This function is as indispensable as flip. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
Jonathan Cast wrote: On Wed, 2009-03-25 at 15:09 +, Simon Marlow wrote: the ordering that the state monad expects (and I can never remember which way around they are in Control.Monad.State). Really? I found it obvious once I figured out it how simple it made (=). With the order from Control.Monad.State (with constructors ignored): a = f = \ s - case s a of (x, s') - f x s' Reversing the order of the components of the result gives you a = f = \ s - case s a of (s', x) - f x s' which just looks weird. It might look weird to you, but that's the way that GHC's IO and ST monads do it. It looks perfectly natural to me! (and you have the a and s the wrong way around in 'case s a', BTW). Try doing it with mapAccumL, which is arguably the right abstraction, but has the components the other way around. Define swap (a, b) = (b, a) ew, that's far too crude. I think you mean swap = uncurry $ flip (,) Cheers, Simon ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
On Wed, Mar 25, 2009 at 4:09 PM, Simon Marlow marlo...@gmail.com wrote: But it only works out nicely because the ordering of the components of the pair returned by splitAt matches the ordering that the state monad expects (and I can never remember which way around they are in Control.Monad.State). Now you mention this, I often had to write a little function swap :: (a,b) - (b,a) It seems many other authors have done the same in their own modules. Maybe this should be part of the Prelude? Try doing it with mapAccumL, which is arguably the right abstraction, but has the components the other way around. Cheers, Simon ___ 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] Re: about Haskell code written to be too smart
Simon Marlow wrote: Jonathan Cast wrote: Define swap (a, b) = (b, a) ew, that's far too crude. I think you mean swap = uncurry $ flip (,) I think I would prefer something that mirrors flip more closely: swap :: ((a,b) - c) - (b,a) - c swap = uncurry . flip . curry - Jake ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
2009/3/25 Zachary Turner divisorthe...@gmail.com: On the other hand, -certain- languages are more expressive than others. As an example, I personally find English far more expressive than both Vietnamese and Japanese, yet English is far more complicated. Japanese, for Way off topic, but for what it's worth, you can take it as axiomatic that all natural languages are equally expressive, qua languages. They're also equally easy/hard overall. The areas of difficulty are just in different places. Japanese grammar is extraordinarily simple, but achieving mastery of the spoken language *in Japanese society* is next to impossible, because usage reflects social constructions. As you no doubt know, what is not said is sometimes just as expressive as what is said in Japanese; very maddening to a logorrheic American, just as an English speaker's need to explicitly articulate *everything* is no doubt annoying to Japanese. Regarding spelling and phonology: the idea that one symbol, one sound is somehow optimal is the Myth That Will Not Die. None other than Chomsky himself argued that English orthography is near-optimal for the English language. All writing systems are designed to serve speakers of the language, and many languages are poorly modeled by a one symbol, one sound system. I'm not sure there's a lesson there for formal language designers and programmers, except maybe that the expressiveness (elegance?) of a text usually depends to a great extent on the writer more than the language. -g ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
On Wed, 25 Mar 2009 08:25:40 -0700 Jonathan Cast jonathancc...@fastmail.fm wrote: Define swap (a, b) = (b, a) By the way, if you want to be too smart, there's a generalised version of swap in Control.Category.Braided in the category-extras package. That might be a bit overkill though. -- Robin ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
On Wed, 2009-03-25 at 03:01 +, Robin Green wrote: On Wed, 25 Mar 2009 08:25:40 -0700 Jonathan Cast jonathancc...@fastmail.fm wrote: Define swap (a, b) = (b, a) By the way, if you want to be too smart, there's a generalised version of swap in Control.Category.Braided in the category-extras package. Thanks, I'll check it out. That might be a bit overkill though. What is this word `overkill' you use? jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Quoth Lennart Augustsson lenn...@augustsson.net: Some examples of what might happen: OK, these are interesting phenomena. From a practical point of view, though, I could see someone weighing the potential costs and benefits of a exception handler outside IO like this, and these effects might not even carry all that much weight. Does that make sense, or is the problem really more dire than I understand? I mean, it isn't the first time I've seen this explained in terms of predictability in a case where there are two possible exceptions, so I have to take for granted that this is a compelling argument to some, but it is evidently a matter of perspective. Donn If you have more than one possible exception in your code, you don't know which one you will get. It can vary between compilers, optimization levels, program runs, or even evaluating the same expression within one program. If you have code that have both an infinite loop and an exception you don't know if you'll get the loop or the exception. Breaking the deterministic behaviour can lead to strange consequences, because the compiler relies on it. For instance, the following code let x = someExpression print x print x could print different values for x the two times you print it. (This is somewhat unlikely, but could happen when evaluating in parallel with ghc, because there is a small window where two threads might start evaluating x and later update x with two different values.) -- Lennart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Wed, 2009-03-25 at 09:15 -0700, Donn Cave wrote: Quoth Lennart Augustsson lenn...@augustsson.net: Some examples of what might happen: OK, these are interesting phenomena. From a practical point of view, though, I could see someone weighing the potential costs and benefits of a exception handler outside IO like this, and these effects might not even carry all that much weight. Well, sure. From a purely `practical' point of view, I don't know why you would even use a purely functional language (as opposed to trying to minimize side effects in an impure language). But if you're not concerned about purity, or ease of equational reasoning, or accuracy of a wide range of compiler transformations/optimizations/because it makes the generated code pretty to sort the formal parameters by name before forcing them-implementation decisions, then please do not use Haskell. There are many other languages that are suitable for what you want to do, and it would be a courtesy to those of us who *do* use Haskell because it is purely functional, not to have to explicitly exclude your library from our picture of the language's capabilities. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Learning Haskell
Learning the syntax, a day or two. Learning major idioms (many of which are encapsulated in modules), ongoing (it's been about two years of off and on). Sadly I can't use it for my $work language. If I could then the time available for learning haskell and paying the mortgage would not be disjoint. On the other hand I'm using what I'm learning at work and it's making for better code. (And scaring some of my coworkers doing my code-reviews. :) -ljr Jon Fairbairn wrote: Tom.Amundsen tomamund...@gmail.com writes: How long did it take you to become proficient in Haskell? Something more than twenty years. By that, I mean - how long until you were just as comfortable with Haskell as you were with your strongest language at that time? Oh, Haskell was my strongest language during all that time! ;-) If I have a serious point, it's that going from writing imperative programmes to writing properly functional ones takes a lot longer than it takes to learn every facet of the language. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Grouping - Map / Reduce
Dear Luke, I'm at a loss trying to figure out what is happening here, I'd sincerely appreciate it if you could find the time to give me more clues on this, I'm deeply impressed. If I think that what is happening *is* happening that would mean that this is a way to group in almost constant space. Günther ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
If you think non-determinstic programs are acceptable, then you can use unsafePerformIO this way. But future versions of compilers may make them even more unpredictable, so beware. I think that if the exception handler does not look at exactly what exception was thrown, then the program will just vary in definedness (i.e., comparable in the domain approximation ordering). Many people consider this acceptable. -- Lennart On Wed, Mar 25, 2009 at 4:15 PM, Donn Cave d...@avvanta.com wrote: Quoth Lennart Augustsson lenn...@augustsson.net: Some examples of what might happen: OK, these are interesting phenomena. From a practical point of view, though, I could see someone weighing the potential costs and benefits of a exception handler outside IO like this, and these effects might not even carry all that much weight. Does that make sense, or is the problem really more dire than I understand? I mean, it isn't the first time I've seen this explained in terms of predictability in a case where there are two possible exceptions, so I have to take for granted that this is a compelling argument to some, but it is evidently a matter of perspective. Donn If you have more than one possible exception in your code, you don't know which one you will get. It can vary between compilers, optimization levels, program runs, or even evaluating the same expression within one program. If you have code that have both an infinite loop and an exception you don't know if you'll get the loop or the exception. Breaking the deterministic behaviour can lead to strange consequences, because the compiler relies on it. For instance, the following code let x = someExpression print x print x could print different values for x the two times you print it. (This is somewhat unlikely, but could happen when evaluating in parallel with ghc, because there is a small window where two threads might start evaluating x and later update x with two different values.) -- Lennart ___ 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] Re: about Haskell code written to be too smart
On Wed, Mar 25, 2009 at 11:32 AM, Simon Marlow marlo...@gmail.com wrote: Jonathan Cast wrote: Define swap (a, b) = (b, a) ew, that's far too crude. I think you mean swap = uncurry $ flip (,) On the theme of using monads where you might not expect, swap = liftA2 (,) snd fst -- Dave Menendez d...@zednenem.com http://www.eyrie.org/~zednenem/ ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
On Wed, 2009-03-25 at 15:32 +, Simon Marlow wrote: Jonathan Cast wrote: On Wed, 2009-03-25 at 15:09 +, Simon Marlow wrote: the ordering that the state monad expects (and I can never remember which way around they are in Control.Monad.State). Really? I found it obvious once I figured out it how simple it made (=). With the order from Control.Monad.State (with constructors ignored): a = f = \ s - case s a of (x, s') - f x s' Reversing the order of the components of the result gives you a = f = \ s - case s a of (s', x) - f x s' which just looks weird. It might look weird to you, but that's the way that GHC's IO and ST monads do it. It looks perfectly natural to me! Right. Consider this an argument for fixing IO/ST(/STM?) to conform to the self-evidently correct ordering of Control.Monad.State :) (and you have the a and s the wrong way around in 'case s a', BTW). Um, yes. /Mea culpa/. Try doing it with mapAccumL, which is arguably the right abstraction, but has the components the other way around. Define swap (a, b) = (b, a) ew, that's far too crude. I think you mean swap = uncurry $ flip (,) Ah, yes. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Quoth Jonathan Cast jonathancc...@fastmail.fm: On Wed, 2009-03-25 at 09:15 -0700, Donn Cave wrote: OK, these are interesting phenomena. From a practical point of view, though, I could see someone weighing the potential costs and benefits of a exception handler outside IO like this, and these effects might not even carry all that much weight. Well, sure. From a purely `practical' point of view, I don't know why you would even use a purely functional language (as opposed to trying to minimize side effects in an impure language). But if you're not concerned about purity, or ease of equational reasoning, or accuracy of a wide range of compiler transformations/optimizations/because it makes the generated code pretty to sort the formal parameters by name before forcing them-implementation decisions, then please do not use Haskell. There are many other languages that are suitable for what you want to do, and it would be a courtesy to those of us who *do* use Haskell because it is purely functional, not to have to explicitly exclude your library from our picture of the language's capabilities. Concerned about purity, ease of equational reasoning, etc.? Sure ... but I guess hoping we can agree on practical reasons for interest in these things, as opposed to, or at least in addition to, their esthetic or religious appeal. I'm guessing you would likewise, if only because a solely esthetic appeal is difficult angle to pursue because people's esthetic sensibilities aren't guaranteed to line up very well. And in fact the way I read the responses so far in this thread, the range of attitudes towards the matter seems pretty wide to me, among people whose views I respect. So I thought it would be interesting to explore statements like you must not do this, and pure Haskell is not allowed to be non-deterministic, in terms of practical effects. No one would make a statement like that and not hope to be challenged on it? Donn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
Simon Marlow wrote: Jonathan Cast wrote: Define swap (a, b) = (b, a) ew, that's far too crude. I think you mean swap = uncurry $ flip (,) I think I would prefer something that mirrors flip more closely: swap :: ((a,b) - c) - (b,a) - c swap = uncurry . flip . curry - Jake ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Hi Duncan and all, On Wed, Mar 25, 2009 at 3:52 AM, Duncan Coutts duncan.cou...@worc.ox.ac.uk wrote: On Mon, 2009-03-23 at 08:11 -0400, Xiao-Yong Jin wrote: tryArith :: a - Either ArithException a tryArith = unsafePerformIO . try . evaluate You must not do this. It breaks the semantics of the language. Other people have given practical reasons why you should not but a theoretical reason is that you've defined a non-continuous function. That is impossible in the normal semantics of pure functional languages. So you're breaking a promise which we rely on. ... Of course your tryArith only tests for certain kinds of _|_ value, but in principle the problem is the same. That's not *quite* how the semantics of Haskell exceptions are defined, actually, unless I'm misunderstanding something or the thinking about it has changed since the original paper on the topic: Simon Peyton Jones, Alastair Reid, Tony Hoare, Simon Marlow, Fergus Henderson: A semantics for imprecise exceptions. SIGPLAN Conference on Programming Language Design and Implementation, 1999. http://www.haskell.org/~simonmar/papers/except.ps.gz In the semantics given by that paper, the value of an expression of type Int is (a) an actual number, or (b) a set of exceptions that the expression might raise when evaluated, or (c) bottom, which means: when evaluated, the expression may not terminate, or may terminate and raise some arbitrary exception. (The semantic ordering is: everything is larger than bottom; a set of expressions A is larger than a set of expressions B iff A is a proper subset of B; numbers are not comparable to sets.) tryArith is still noncontinuous, though, and nondeterministic, too. Consider: divzero = 1/0 overflow = 2**1000 loop = loop - 1 * What is (tryArith (divzero + overflow))? The denotational value of (divzero + overflow) is the set {DivideByZero, Overflow}, so tryArith can return either (Left DivideByZero) or (Left Overflow) -- nondeterminism. * What is (tryArith (overflow + loop))? The denotational value of (overflow + loop) is bottom, so tryArith can theoretically return any arithmetic exception, or propagate any non-arithmetic exception, or loop forever. In practice, of course, it will either return (Left Overflow), or loop forever, or error out if the compiler notices the loop. However, this still means that it *may* return (Left Overflow) even though the semantical value of (overflow + loop) is bottom, which means that the function is not monotone and thus not continuous. All the best, - Benja ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: Learning Haskell
I discovered Haskell about a year and half ago, along with F#. Beginning with both languages was relatively easy but I already had experience of FP in lisp and scheme. And some years ago I took a course in FP (learning CAML which F# is closely based on). My study of haskell went smooth up to the point I came across monads (that is, the honey moon did not last very long). I must admit that it took me about 3 months of (intermittent) work to first understand monads and then to be able to use them correctly. What also helped me a lot was the parallel study of both F# and Haskell. Indeed, I often tried to understand how some constructs in Haskell could or could not be implemented in F# (i.e type classes). I.e. that really helped me understand the higher order types in Haskell. After the monad episode, I found myself quite interested in FRP and all its lot of new concepts (applicative functors, arrows, ...). I tried to read as much as I could on the subject and finally decided that if I wanted to really understand all this, one of the best solution was trying to implement a small FRP myself. That's what I did in F#. After a few weeks, I think I now understand arrows, application functors and other curiosities. I think that working on more or less real problems (or on real applications) is definitively the best way to learn such languages. It is not a matter of writing thousands of lines of code but rather to pick up a specific aspect/feature of a language and to apply it to a concrete example, just to understand what problem it is supposed to solve and how well it solves it. Although I am not making a living on Haskell/F# (specially in my country), it gave me quite a lot of good idea in my day to day work both in terms of development techniques and in terms of analysis/specifications. So learning Haskell was not the easiest thing I did in my life but so far, it does pay off. J-C On Wed, Mar 25, 2009 at 5:28 PM, Lanny Ripple la...@cisco.com wrote: Learning the syntax, a day or two. Learning major idioms (many of which are encapsulated in modules), ongoing (it's been about two years of off and on). Sadly I can't use it for my $work language. If I could then the time available for learning haskell and paying the mortgage would not be disjoint. On the other hand I'm using what I'm learning at work and it's making for better code. (And scaring some of my coworkers doing my code-reviews. :) -ljr Jon Fairbairn wrote: Tom.Amundsen tomamund...@gmail.com writes: How long did it take you to become proficient in Haskell? Something more than twenty years. By that, I mean - how long until you were just as comfortable with Haskell as you were with your strongest language at that time? Oh, Haskell was my strongest language during all that time! ;-) If I have a serious point, it's that going from writing imperative programmes to writing properly functional ones takes a lot longer than it takes to learn every facet of the language. ___ 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] Use unsafePerformIO to catch Exception?
On Wed, 2009-03-25 at 10:00 -0700, Donn Cave wrote: Quoth Jonathan Cast jonathancc...@fastmail.fm: On Wed, 2009-03-25 at 09:15 -0700, Donn Cave wrote: OK, these are interesting phenomena. From a practical point of view, though, I could see someone weighing the potential costs and benefits of a exception handler outside IO like this, and these effects might not even carry all that much weight. Well, sure. From a purely `practical' point of view, I don't know why you would even use a purely functional language (as opposed to trying to minimize side effects in an impure language). But if you're not concerned about purity, or ease of equational reasoning, or accuracy of a wide range of compiler transformations/optimizations/because it makes the generated code pretty to sort the formal parameters by name before forcing them-implementation decisions, then please do not use Haskell. There are many other languages that are suitable for what you want to do, and it would be a courtesy to those of us who *do* use Haskell because it is purely functional, not to have to explicitly exclude your library from our picture of the language's capabilities. Concerned about purity, ease of equational reasoning, etc.? Sure ... but I guess hoping we can agree on practical reasons for interest in these things, as opposed to, or at least in addition to, their esthetic or religious appeal. I'm guessing you would likewise, Nope. You must not have been following my positions in previous discussions. I am committed to functional purity for its own sake (just as I am committed to software development for its own sake; don't you *dare* suggest using Global Script!) if only because a solely esthetic appeal is difficult angle to pursue because people's esthetic sensibilities aren't guaranteed to line up very well. And in fact the way I read the responses so far in this thread, the range of attitudes towards the matter seems pretty wide to me, among people whose views I respect. So I thought it would be interesting to explore statements like you must not do this, and pure Haskell is not allowed to be non-deterministic, in terms of practical effects. No one would make a statement like that and not hope to be challenged on it? What? Challenged by people who think Haskell should not be a purely functional language? I mean, that's kind of what it is. Again, if you don't want to use a purely functional language, there are *lots* of impure languages out there. There's no need to turn Haskell into one of them. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] central european functional programming school
Hi, I'm interested in 3rd central european functional programming school[1]. Maybe some haskellers attended previous CEFPs and want to share (or already shared) some experience? Who also is going to attend or participate in this year's CEFP? 1. http://plcportal.inf.elte.hu/en/tfp_cefp_2009/Pages/default.aspx -- Roman I. Cheplyaka :: http://ro-che.info/ Don't let school get in the way of your education. - Mark Twain ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Whats the use of !
I have seen ! added in front of many values, is it related to strict evaluation? Please elaborate on it. TIA, gimli _ Windows Live Messenger. Multitasking at its finest. http://www.microsoft.com/india/windows/windowslive/messenger.aspx___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Whats the use of !
Hi A quick Hoogle for ! : http://haskell.org/hoogle/?hoogle=! Gives the first answer as: http://www.haskell.org/haskellwiki/Keywords#.21 If that isn't clear, someone should expand on it or give further links to useful resources. Thanks Neil 2009/3/25 Harsh Verma hjve...@hotmail.com: I have seen ! added in front of many values, is it related to strict evaluation? Please elaborate on it. TIA, gimli Windows Live Messenger. Multitasking at its finest. ___ 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] Re: about Haskell code written to be too smart
or via Arrow: swap = snd fst On Wed, Mar 25, 2009 at 9:16 AM, David Menendez d...@zednenem.com wrote: On Wed, Mar 25, 2009 at 11:32 AM, Simon Marlow marlo...@gmail.com wrote: Jonathan Cast wrote: Define swap (a, b) = (b, a) ew, that's far too crude. I think you mean swap = uncurry $ flip (,) On the theme of using monads where you might not expect, swap = liftA2 (,) snd fst -- Dave Menendez d...@zednenem.com http://www.eyrie.org/~zednenem/ http://www.eyrie.org/%7Ezednenem/ ___ 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] Use unsafePerformIO to catch Exception?
Quoth Jonathan Cast jonathancc...@fastmail.fm: On Wed, 2009-03-25 at 10:00 -0700, Donn Cave wrote: So I thought it would be interesting to explore statements like you must not do this, and pure Haskell is not allowed to be non-deterministic, in terms of practical effects. No one would make a statement like that and not hope to be challenged on it? What? Challenged by people who think Haskell should not be a purely functional language? I mean, that's kind of what it is. Again, if you don't want to use a purely functional language, there are *lots* of impure languages out there. There's no need to turn Haskell into one of them. OK. You may note that I didn't actually pose any questions to you until engaged directly, having already surmised that answers were not forthcoming. But for the record, I should note that I haven't proposed any changes to Haskell, recently or that I recall even in the distant past except for one idea I had about pattern matching in a lambda expression. Donn ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] How to increment an Int in Haskell (stack overflow issue)
I have a program that is currently blowing out the stack, Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. I am pretty sure I get to the end of the computation that increments various statistic counters (lazily?) and only when I go to print them out at the end, do things fail. I have state monad transformer (StateT) that is keeping the counters among other things. The counters are stored in a pair within a larger data structure. data AState s a = AS { ... asStats :: (Int,Int) ... } to increment them I initially just simply applied either of incFst, incSnd :: (Int,Int) - (Int,Int) incFst (x,y) = (x + 1,y) incSnd (x,y) = (x, y + 1) to the current pair. I thought this was safe since primitive arithmetic was strict, but when I go to print the counter out (evaluate it), it blows apart. I first decided this was because the addition was somehow not strict and I was getting: (0 + 1 + 1 ...millions of times..., ) and the evaluation of that first coordinate blew things apart. So I tried was adding a strictness annotation to the arguments. incFst (!x,y) = (x + 1,y) incSnd (x,!y) = (x, y + 1) No dice (I also tried using seq manually all over the place to no avail). Just for fun, I tried both of incFst _ = (0,0) incSnd _ = (0,0) and incFst (x,y) = (x,y) incSnd (x,y) = (x,y) The problem goes away. But maybe an optimization is covering up the crime. So I tried incFst (x,y) = (y,x) incSnd (x,y) = (y,x) And indeed this again crashes. Any hints as to what is going on? If it is relevant, here is my code to access the counter within the state monad countFst :: StateT (AState s a) IO () countFst = modify $ \as - as{asStats = incFst (asStats as)} and the monad transformer I am using is import Control.Monad.State.Strict ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Thomas Hartman wrote: sorry, wrong function. should be partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) It's not tail recursive, FWIW. The recursive expression has (:) as it's head before it hits `partitions`. It is however nicely coinductive, which has other good properties. We could make it tail-recursive easily, partitions = go id where go k [] xs = k [] go k (n:ns) xs = let (beg,end) = splitAt n xs k'= k . (beg:) in case end of [] - k' [] xs' - go k' ns xs' (Note how this version has `go` as the head of the recursive expression.) ...however this version has different strictness properties. In particular, let both input lists be infinite (and take a finite portion of the result). The original version works fine because it gives a little bit of output (beg:) at each step of the recursion ---which is all coinductive means. The tail-recursive version hits _|_ however, because we've delayed giving any input (k []) until one of the two lists hits [] ---we've tried doing induction on co-data and so we hit an infinite loop. This dichotomy between coinduction and tail-recursion is quite common. It's another example of the recently discussed problem of defining foldr in terms of foldl. Whether the termination differences matter depends on how the function is to be used. Another nice property of coinduction is that it means we can do build/fold fusion easily: partitions = \ns xs - build (\cons nil - go cons nil ns xs) where go cons nil = go' where go' [] xs = nil go' (n:ns) xs = let (beg,end) = splitAt n xs in beg `cons` case end of [] - nil xs' - go' ns xs' By using the GHC.Exts.build wrapper the fusion rules will automatically apply. The second wrapper, go, is just so that the worker, go', doesn't need to pass cons and nil down through the recursion. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Making videos of your project
Cool! Thanks, Don. I enjoyed the show :) Duane Johnson On Mar 24, 2009, at 2:20 AM, Don Stewart wrote: Hey guys, I've been making quick youtube videos of projects to convey what they do. Here, for example, using Tim Docker's Charts library in ghci: http://www.youtube.com/watch?v=2Lqzygxvus0 (Click on the HD button for higher res). Or one of Neil Brown's SG OpenGL graphics library, http://www.youtube.com/watch?v=tJ6AtfcorkY You can create your own really simply: 1. install 'recordmydesktop' I use: recordmydesktop --no-sound --v_bitrate 200 2. type 'recordmydesktop' 3. do something with haskell 4. hit control-C 5. upload out.ogv to youtube If you're a library author of one of the 2 or 3D packages, please consider video along with other why I want to use this material. -- Don ___ 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] How to increment an Int in Haskell (stack overflow issue)
Make an AState with two !Int fields and increment those. On Wed, Mar 25, 2009 at 8:00 PM, Tim Bauer bauer...@eecs.orst.edu wrote: I have a program that is currently blowing out the stack, Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. I am pretty sure I get to the end of the computation that increments various statistic counters (lazily?) and only when I go to print them out at the end, do things fail. I have state monad transformer (StateT) that is keeping the counters among other things. The counters are stored in a pair within a larger data structure. data AState s a = AS { ... asStats :: (Int,Int) ... } to increment them I initially just simply applied either of incFst, incSnd :: (Int,Int) - (Int,Int) incFst (x,y) = (x + 1,y) incSnd (x,y) = (x, y + 1) to the current pair. I thought this was safe since primitive arithmetic was strict, but when I go to print the counter out (evaluate it), it blows apart. I first decided this was because the addition was somehow not strict and I was getting: (0 + 1 + 1 ...millions of times..., ) and the evaluation of that first coordinate blew things apart. So I tried was adding a strictness annotation to the arguments. incFst (!x,y) = (x + 1,y) incSnd (x,!y) = (x, y + 1) No dice (I also tried using seq manually all over the place to no avail). Just for fun, I tried both of incFst _ = (0,0) incSnd _ = (0,0) and incFst (x,y) = (x,y) incSnd (x,y) = (x,y) The problem goes away. But maybe an optimization is covering up the crime. So I tried incFst (x,y) = (y,x) incSnd (x,y) = (y,x) And indeed this again crashes. Any hints as to what is going on? If it is relevant, here is my code to access the counter within the state monad countFst :: StateT (AState s a) IO () countFst = modify $ \as - as{asStats = incFst (asStats as)} and the monad transformer I am using is import Control.Monad.State.Strict ___ 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] ghci + hopengl
Neat, thanks for that tip Peter. It looks like mkbundl does everything I do manually, and more. But just for the record, in case anyone (Scott?) wants to do it the hard way... :) 1. Download the macosx-app shell script from wxhaskell. Make it executable (i.e. chmod a+x macosx-app) 2. Run macosx-app [executable-filename], e.g. macosx-app Playground 3. Run open [generated app directory], e.g. open Playground.app I also blogged about it here. Duane Johnson http://blog.inquirylabs.com/ On Mar 24, 2009, at 4:48 PM, Peter Verswyvelen wrote: On Tue, Mar 24, 2009 at 11:35 PM, Scott A. Waterman tswater...@gmail.com wrote: Duane - yes, please. I've been wondering how to compile to a Mac .app structure. http://hackage.haskell.org/cgi-bin/hackage-scripts/package/mkbndl Also, anyone have any hints about distributing Haskell apps for mac, when you know the target will certianly *not* have a GHC environment on it? GHC statically links everything, so you don't need the GHC environment to run the app. Thanks --ts On Mar 21, 2009, at 2:18 PM, Duane Johnson wrote: I've had issues with ghci and opengl... I usually have to compile my programs before they will run. I'm not sure why that's the case, but I too get strange window behavior (sometimes it freezes, other times it doesn't even show up). If you're on a Mac and would like help compiling to a .app folder, let me know and I can post how I did that. Regards, Duane Johnson http://blog.inquirylabs.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] about Haskell code written to be too smart
So to be clear with the terminology: inductive = good consumer? coinductive = good producer? So fusion should be possible (automatically? or do I need a GHC rule?) with inductive . coinductive Or have I bungled it? Dan wren ng thornton wrote: Thomas Hartman wrote: sorry, wrong function. should be partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) It's not tail recursive, FWIW. The recursive expression has (:) as it's head before it hits `partitions`. It is however nicely coinductive, which has other good properties. We could make it tail-recursive easily, partitions = go id where go k [] xs = k [] go k (n:ns) xs = let (beg,end) = splitAt n xs k'= k . (beg:) in case end of [] - k' [] xs' - go k' ns xs' (Note how this version has `go` as the head of the recursive expression.) ...however this version has different strictness properties. In particular, let both input lists be infinite (and take a finite portion of the result). The original version works fine because it gives a little bit of output (beg:) at each step of the recursion ---which is all coinductive means. The tail-recursive version hits _|_ however, because we've delayed giving any input (k []) until one of the two lists hits [] ---we've tried doing induction on co-data and so we hit an infinite loop. This dichotomy between coinduction and tail-recursion is quite common. It's another example of the recently discussed problem of defining foldr in terms of foldl. Whether the termination differences matter depends on how the function is to be used. Another nice property of coinduction is that it means we can do build/fold fusion easily: partitions = \ns xs - build (\cons nil - go cons nil ns xs) where go cons nil = go' where go' [] xs = nil go' (n:ns) xs = let (beg,end) = splitAt n xs in beg `cons` case end of [] - nil xs' - go' ns xs' By using the GHC.Exts.build wrapper the fusion rules will automatically apply. The second wrapper, go, is just so that the worker, go', doesn't need to pass cons and nil down through the recursion. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Are you saying there's a problem with this implementation? It's the Yes, there is actually a problem with this implementation. import Data.List import Control.Monad.State import Debug.Trace.Helpers partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) partitionsSimpleStupidGood = partitions partitionsTooFrickinClever = evalState . mapM (State . splitAt) testP pf = mapM_ putStrLn [ show . pf [3,7..] $ [1..10] , show . pf [3,7,11,15] $ [1..] , show . head . last $ pf [3,3..] [1..10^6] ] *Main testP partitionsSimpleStupidGood testP partitionsSimpleStupidGood^J[[1,2,3],[4,5,6,7,8,9,10]] [[1,2,3],[4,5,6,7,8,9,10],[11,12,13,14,15,16,17,18,19,20,21],[22,23,24,25,26,27,28,29,30,31,32,33,34,35,36]] 100 Now try testP partitionsTooFrickinClever Now, I am sure there is a fix for whatever is ailing the State monad version, and we would all learn a lesson from it about strictness, laziness, and the State monad. However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. So... I insist... Easy for a beginner to read == better! 2009/3/24 Dan Piponi dpip...@gmail.com: Miguel Mitrofanov wrote: takeList = evalState . mapM (State . splitAt) However, ironically, I stopped using them for pretty much the same reason that Manlio is saying. Are you saying there's a problem with this implementation? It's the only one I could just read immediately. The trick is to see that evalState and State are just noise for the type inferencer so we just need to think about mapM splitAt. This turns a sequence of integers into a sequence of splitAts, each one chewing on the leftovers of the previous one. *Way* easier than both the zipWith one-liner and the explicit version. It says exactly what it means, almost in English. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. So... I insist... Easy for a beginner to read == better! All you have said is that one building a skyscraper will need scaffolding, blueprints, and a good building inspector. The intended inhabitants of that skyscraper will not want to stare out at scaffolding for the rest of their lives. Put the simple version in a QuickCheck predicate. That is the ideal place for it. All the better if through this process we all learn a lesson about strictness, laziness, and the State monad. Dan Thomas Hartman wrote: Are you saying there's a problem with this implementation? It's the Yes, there is actually a problem with this implementation. import Data.List import Control.Monad.State import Debug.Trace.Helpers partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) partitionsSimpleStupidGood = partitions partitionsTooFrickinClever = evalState . mapM (State . splitAt) testP pf = mapM_ putStrLn [ show . pf [3,7..] $ [1..10] , show . pf [3,7,11,15] $ [1..] , show . head . last $ pf [3,3..] [1..10^6] ] *Main testP partitionsSimpleStupidGood testP partitionsSimpleStupidGood^J[[1,2,3],[4,5,6,7,8,9,10]] [[1,2,3],[4,5,6,7,8,9,10],[11,12,13,14,15,16,17,18,19,20,21],[22,23,24,25,26,27,28,29,30,31,32,33,34,35,36]] 100 Now try testP partitionsTooFrickinClever Now, I am sure there is a fix for whatever is ailing the State monad version, and we would all learn a lesson from it about strictness, laziness, and the State monad. However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. So... I insist... Easy for a beginner to read == better! 2009/3/24 Dan Piponi dpip...@gmail.com: Miguel Mitrofanov wrote: takeList = evalState . mapM (State . splitAt) However, ironically, I stopped using them for pretty much the same reason that Manlio is saying. Are you saying there's a problem with this implementation? It's the only one I could just read immediately. The trick is to see that evalState and State are just noise for the type inferencer so we just need to think about mapM splitAt. This turns a sequence of integers into a sequence of splitAts, each one chewing on the leftovers of the previous one. *Way* easier than both the zipWith one-liner and the explicit version. It says exactly what it means, almost in English. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] How to increment an Int in Haskell (stack overflow issue)
Am Mittwoch 25 März 2009 20:00:40 schrieb Tim Bauer: I have a program that is currently blowing out the stack, Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. I am pretty sure I get to the end of the computation that increments various statistic counters (lazily?) Far too lazily. and only when I go to print them out at the end, do things fail. I have state monad transformer (StateT) that is keeping the counters among other things. The counters are stored in a pair within a larger data structure. data AState s a = AS { ... asStats :: (Int,Int) ... } The problem goes away. But maybe an optimization is covering up the crime. So I tried incFst (x,y) = (y,x) incSnd (x,y) = (y,x) And indeed this again crashes. Any hints as to what is going on? If it is relevant, here is my code to access the counter within the state monad countFst :: StateT (AState s a) IO () countFst = modify $ \as - as{asStats = incFst (asStats as)} This is where the strictness you added to incFst is hidden again. countFst writes the thunk (\as - as{asStats = incFst (asStats as)}) to the state, incFst isn't even called yet. To force the evaluation, a) make the stats two strict (!Int) fields b) evaluate the state, like in countFst = do as - get let a = asStats1 as as1 = as{asStats1 = a+1} put $! as1 and the monad transformer I am using is import Control.Monad.State.Strict ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
On Wed, 2009-03-25 at 12:48 -0700, Dan Weston wrote: However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. So... I insist... Easy for a beginner to read == better! All you have said is that one building a skyscraper will need scaffolding, blueprints, and a good building inspector. The intended inhabitants of that skyscraper will not want to stare out at scaffolding for the rest of their lives. +1 jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Oh, and incidentally, if you change to Control.Monad.State.Strict *Main testP partitionsTooFrickinClever testP partitionsTooFrickinClever^J*** Exception: stack overflow Don't get me wrong -- I have learned a lot from this thread, and I think it would be really cool if there was a way to do this that is clever, that is *right*. But since the original point was about style, I think this underscores the point that good style should be newbie friendly *if possible*. Especially since being a newbie in haskell isn't like in other languages -- might mean you have been using it for years as a hobby, but just don't have comfort in certain monads and idioms. 2009/3/25 Thomas Hartman tphya...@gmail.com: Are you saying there's a problem with this implementation? It's the Yes, there is actually a problem with this implementation. import Data.List import Control.Monad.State import Debug.Trace.Helpers partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) partitionsSimpleStupidGood = partitions partitionsTooFrickinClever = evalState . mapM (State . splitAt) testP pf = mapM_ putStrLn [ show . pf [3,7..] $ [1..10] , show . pf [3,7,11,15] $ [1..] , show . head . last $ pf [3,3..] [1..10^6] ] *Main testP partitionsSimpleStupidGood testP partitionsSimpleStupidGood^J[[1,2,3],[4,5,6,7,8,9,10]] [[1,2,3],[4,5,6,7,8,9,10],[11,12,13,14,15,16,17,18,19,20,21],[22,23,24,25,26,27,28,29,30,31,32,33,34,35,36]] 100 Now try testP partitionsTooFrickinClever Now, I am sure there is a fix for whatever is ailing the State monad version, and we would all learn a lesson from it about strictness, laziness, and the State monad. However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. So... I insist... Easy for a beginner to read == better! 2009/3/24 Dan Piponi dpip...@gmail.com: Miguel Mitrofanov wrote: takeList = evalState . mapM (State . splitAt) However, ironically, I stopped using them for pretty much the same reason that Manlio is saying. Are you saying there's a problem with this implementation? It's the only one I could just read immediately. The trick is to see that evalState and State are just noise for the type inferencer so we just need to think about mapM splitAt. This turns a sequence of integers into a sequence of splitAts, each one chewing on the leftovers of the previous one. *Way* easier than both the zipWith one-liner and the explicit version. It says exactly what it means, almost in English. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Since this thread is ostensibly about haskell style, it should also be about haskell style *today*. As I think Yitz noted earlier, this is a moving target. Adoption of haskell by the masses -- moving. Skill of haskell hordes -- moving. Abstractions available as part of idiomatic haskell, and correctness of these abstractions, as the state monad for partitions cockup shows -- also moving. 2009/3/25 Jonathan Cast jonathancc...@fastmail.fm: On Wed, 2009-03-25 at 12:48 -0700, Dan Weston wrote: However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. So... I insist... Easy for a beginner to read == better! All you have said is that one building a skyscraper will need scaffolding, blueprints, and a good building inspector. The intended inhabitants of that skyscraper will not want to stare out at scaffolding for the rest of their lives. +1 jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] How to increment an Int in Haskell (stack overflow issue)
bauertim: I have a program that is currently blowing out the stack, Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. I am pretty sure I get to the end of the computation that increments various statistic counters (lazily?) and only when I go to print them out at the end, do things fail. I have state monad transformer (StateT) that is keeping the counters among other things. The counters are stored in a pair within a larger data structure. data AState s a = AS { ... asStats :: (Int,Int) ... } I would always, always write this as: data AState s a = AS { ... , asStatsX, asStatsY :: !Int , ... } and compile with: ghc -O2 -funbox-strict-fields Simple heuristic: unless otherwise specified, atomic types should always be strict fields. -- Don ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Not only is your simpler function easier to read, it is also more correct. partitionsHubris xs ns = zipWith take ns . init $ scanl (flip drop) xs ns partitionsBeginner :: [Int] - [a] - [[a]] partitionsBeginner [] _ = [] partitionsBeginner _ [] = [] partitionsBeginner (n : ns) xs = head : partitionsBeginner ns tail where (head, tail) = splitAt n xs Run both through testP to see why,. testP pf = mapM_ putStrLn [ show . pf [3,7..] $ [1..10] , show . pf [3,7,11,15] $ [1..] , show . head . last $ pf [3,3..] [1..10^6] ] Of course, I favor partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) which to my eyes is even easier to read (and also correct). Pattern matching is awesome language feature. use it! 2009/3/24 Manlio Perillo manlio_peri...@libero.it: Tim Newsham ha scritto: These friends are very interested in Haskell, but it seems that the main reason why they don't start to seriously learning it, is that when they start reading some code, they feel the Perl syndrome. That is, code written to be too smart, and that end up being totally illegible by Haskell novice. I too have this feeling, from time to time. Since someone is starting to write the Haskell coding style, I really suggest him to take this problem into strong consideration. When you think about it, what you are saying is that Haskell programmers shouldn't take advantage of the extra tools that Haskell provides. No, I'm not saying this. But, as an example, when you read a function like: buildPartitions xs ns = zipWith take ns . init $ scanl (flip drop) xs ns that can be rewritten (argument reversed) as: takeList :: [Int] - [a] - [[a]] takeList [] _ = [] takeList _ [] = [] takeList (n : ns) xs = head : takeList ns tail where (head, tail) = splitAt n xs I think that there is a problem. The buildPartition contains too many blocks. And I have read code with even more blocks in one line. It may not be a problem for a seasoned Haskell programmer, but when you write some code, you should never forget that your code will be read by programmers that can not be at your same level. I think that many Haskell programmers forget this detail, and IMHO this is wrong. Haskell provides the ability to abstract code beyond what many other programming systems allow. This abstraction gives you the ability to express things much more tersely. This makes the code a lot harder to read for people who are not familiar with the abstractions being used. The problem is that I have still problems at reading and understanding code that is too much terse... Because I have to assemble in my mind each block, and if there are too many blocks I have problems. [...] Manlio ___ 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] about Haskell code written to be too smart
s/Pattern matching is awesome language feature. use it! /Pattern matching is awesome language feature. Don't be ashamed to use it! / :) 2009/3/25 Thomas Hartman tphya...@gmail.com: Not only is your simpler function easier to read, it is also more correct. partitionsHubris xs ns = zipWith take ns . init $ scanl (flip drop) xs ns partitionsBeginner :: [Int] - [a] - [[a]] partitionsBeginner [] _ = [] partitionsBeginner _ [] = [] partitionsBeginner (n : ns) xs = head : partitionsBeginner ns tail where (head, tail) = splitAt n xs Run both through testP to see why,. testP pf = mapM_ putStrLn [ show . pf [3,7..] $ [1..10] , show . pf [3,7,11,15] $ [1..] , show . head . last $ pf [3,3..] [1..10^6] ] Of course, I favor partitions [] xs = [] partitions (n:parts) xs = let (beg,end) = splitAt n xs in beg : ( case end of [] - [] xs - partitions parts xs) which to my eyes is even easier to read (and also correct). Pattern matching is awesome language feature. use it! 2009/3/24 Manlio Perillo manlio_peri...@libero.it: Tim Newsham ha scritto: These friends are very interested in Haskell, but it seems that the main reason why they don't start to seriously learning it, is that when they start reading some code, they feel the Perl syndrome. That is, code written to be too smart, and that end up being totally illegible by Haskell novice. I too have this feeling, from time to time. Since someone is starting to write the Haskell coding style, I really suggest him to take this problem into strong consideration. When you think about it, what you are saying is that Haskell programmers shouldn't take advantage of the extra tools that Haskell provides. No, I'm not saying this. But, as an example, when you read a function like: buildPartitions xs ns = zipWith take ns . init $ scanl (flip drop) xs ns that can be rewritten (argument reversed) as: takeList :: [Int] - [a] - [[a]] takeList [] _ = [] takeList _ [] = [] takeList (n : ns) xs = head : takeList ns tail where (head, tail) = splitAt n xs I think that there is a problem. The buildPartition contains too many blocks. And I have read code with even more blocks in one line. It may not be a problem for a seasoned Haskell programmer, but when you write some code, you should never forget that your code will be read by programmers that can not be at your same level. I think that many Haskell programmers forget this detail, and IMHO this is wrong. Haskell provides the ability to abstract code beyond what many other programming systems allow. This abstraction gives you the ability to express things much more tersely. This makes the code a lot harder to read for people who are not familiar with the abstractions being used. The problem is that I have still problems at reading and understanding code that is too much terse... Because I have to assemble in my mind each block, and if there are too many blocks I have problems. [...] Manlio ___ 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] about Haskell code written to be too smart
Manlio Perillo wrote: The main problem, here, is that: - recursion and pattern matching are explained in every tutorial about functional programming and Haskell. This is the reason why I find them more natural. - high level, Haskell specific, abstractions, are *not* explained in normal tutorials or books. The libraries where these concepts are implemented, are not well documented. This latter point is indeed the problem. But it may be worth rephrasing a bit. The big problem with the Haskell tutorials I've seen is that they aim to teach orthodoxy rather than orthopraxy. Or to put it less religiously, they teach the nuts and bolts of how the language is _constructed_, instead of teaching the idioms and ideas of how the language is _used_. It's like learning C from KernighanRitchie ---a fine book, don't get me wrong, but it teaches the words of the language instead of the community of the speakers. If you've memorized KR you're still a novice C programmer. Given our history, this approach made sense. Haskell's been around for a long time, but most of that history has been in academia where it's assumed that people will know what to do if only they knew how to do it. More recently Haskell has been moving from academic toy to industrial tool, and that shift necessitates a similar shift from teaching the language as a collection of interesting features to teaching the language as a collection of interesting libraries. History hinders this transition--- both the internal history of those who know Haskell (and thus can teach it but only as they know it), and also the external history of the mainstream which understands imperativistic thinking but not functional declarative thinking (and thus we must teach the features in order to give the understanding necessary for teaching the libraries). Recently Galois has been focusing on developing the infrastructure necessary for having easy access to libraries. To this day CPAN is the reason why Perl is one of the best languages out there. Other languages have tried emulating that repository, but the only one I've seen that has the community necessary to make it fly has been Hackage; and the development of Cabal/Hackage is very recent and still very bleeding edge (with the scars to prove it). With Galois' support, I think most Haskellers are aware of Hackage now, however it still hasn't made it into the tutorials in the same way that CPAN is integral to the teaching of Perl. Real World Haskell is another groundbreaking, but recent, development. It's a great book in itself and groundbreaking for embracing open-development in the publishing industry, but it's also the first of this shift from teaching Haskell = Patterns + Recursion + Laziness + Class to teaching modern Haskell in a more holistic community-oriented way. It's worth reiterating that RWH was not the cause of the shift in the community, but is rather a result of the ongoing shift. The Typeclassopedia is another drop in this river: excellent, recent. So I agree that most of the tutorials are lagging behind the modern form of Haskell, but I think this is due in part to a very recent change in the growth and direction of the community. As always with avoiding success at all costs, whether we end up the better for it in the end will depend on holding onto enough newcomers who have only ever known this modern Haskell, because they are the ones who will have the proper perspective to write tutorials and teach the language as if it's always been this way. You must be the change you wish to see in the world. Most of the documentation is in research papers, and a normal programmer don't want to read these papers. Yes, and no. There is quite a bit of documentation in research papers, and mainstream programmers don't read research. However, this is a big part of what makes the Haskell community what it is. There are plenty of non-academics here, but they have the willingness to read these papers (even if it's out of the ordinary) and the desire to learn radical new things (because they're out of the ordinary). A good deal of the papers these days are eminently readable by the laity, moreso than other research papers in computer science or programming languages IMO. This is one of the big things that separates Haskell from the mainstream, but it's not something I see going away any time soon. Given the recent surge of interest from the mainstream, I think it's finally time that we take a more proactive approach in trying to teach this aspect as one of the tenants of our community. Presently there's still a take it or leave it tenor to these discussions, and that needs to be dispelled before it poisons the relations between the old guard and the young turks. New tutorials need to find some way of introducing non-academics to the idea that the academy is not an ivory tower and that part of what makes Haskell cool is the fact that it
Re: [Haskell-cafe] [ANN] ansi-terminal, ansi-wl-pprint - ANSI terminal support for Haskell
Max Bolingbroke wrote: These two packages allow Haskell programs to produce much richer console output by allowing colorisation, emboldening and so on. Both Unix-like (OS X, Linux) and Windows operating systems are supported (via a pure Haskell ANSI emulation layer for Windows). Examples, screenshots, and lots more information about how to get the packages are available at the freshly-minted homepages: http://batterseapower.github.com/ansi-terminal/ http://batterseapower.github.com/ansi-wl-pprint/ These two packages have actually been in stealth release mode on Hackage for some time. However, they seem to be getting some use and I'm not getting any bug reports, so I figure that they /must/ be stable enough to make a proper announcement :-) I use ANSI-Terminal all the time - AND I'M ON WINDOWS! ;-) ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [ANN] ansi-terminal, ansi-wl-pprint - ANSI terminal support for Haskell
On Wed, 2009-03-25 at 21:18 +, Andrew Coppin wrote: I'M ON WINDOWS! ;-) We've noticed... jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] [ANN] I/O library for Windows
Felix Martini wrote: Hi all, winio is an I/O library for Windows using Windows API functions and has I/O completion port support. The main goal of this library is to support Simon Marlow's new Handle API once he has added that to GHC. The library also has a compatibility module for socket functions from the network-bytestring package. Because the library uses IOCP instead of select it is not limited to 1024 open sockets. Try for example the thread-ring program where each Haskell thread passes a UDP message around (Change the MaxUserPort field in HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to 65534 to enable all ports). The winio package is available on Hackage. Notice that it uses a development version of the network package which is available at http://darcs.haskell.org/packages/network/. The library has not been tested much and should be considered experimental so please try it if you use Windows and notify me of any issue or corner case. As I understand it, programs compiled with GHC currently use MSYS for all I/O operations, resulting in all kinds of strange behaviour in corner cases. (E.g., if you use System.Directory and ask whether C:\\ is a directory, it says no, yet you can read the contents of that directory.) I would have thought that calling the Win32 API directly would probably fix most of these minor glitches. Is that what this package is intending to do? ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] ANNOUNCE: WinGhci, a GUI for GHCI on Windows
Pepe Gallardo wrote: Hi, I am pleased to announce the first release of WinGhci. WinGhci is a simple GUI for GHCI on Windows. It is closely based on WinHugs, and provides similar functionality. This is now #1 on my list of things that must be tried. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Learning Haskell
Tom.Amundsen wrote: How long did it take you to become proficient in Haskell? By that, I mean - how long until you were just as comfortable with Haskell as you were with your strongest language at that time? I probably shouldn't even answer that. I keep thinking I only just found out about Haskell, but I have PDF files containing Haskell tutorials, written by me, dated 2005 and earlier. o_O How long did it take to be comfortable with Haskell? A few weeks, I think. How long did it take to become an expert? Ask me when I become an expert! It seems to me that Haskell is like Go: The rules are easy. The strategies for using them... are not. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Wed, 25 Mar 2009, Jonathan Cast wrote: On Wed, 2009-03-25 at 07:39 -0400, Xiao-Yong Jin wrote: Could you elaborate more about why this kind of breakage wouldn't happen if 'try' is used in an IO monad as intended? It would. But it would happen in IO, which is allowed to be non-deterministic. Pure Haskell is not allowed to be non-deterministic. In my opinion, 'try' catching 'error's is still a hack, since 'error's aka bottom mean programming error. Thus catching them is debugging, bug hiding or something worse, but not exception handling. 'try' and friends should be limited to exceptional outcomes of IO actions, e.g. disk full, file read protected etc. There might be a variant 'unsafeTry' which can also block 'error's. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Wed, 2009-03-25 at 22:32 +0100, Henning Thielemann wrote: On Wed, 25 Mar 2009, Jonathan Cast wrote: On Wed, 2009-03-25 at 07:39 -0400, Xiao-Yong Jin wrote: Could you elaborate more about why this kind of breakage wouldn't happen if 'try' is used in an IO monad as intended? It would. But it would happen in IO, which is allowed to be non-deterministic. Pure Haskell is not allowed to be non-deterministic. In my opinion, 'try' catching 'error's is still a hack, since 'error's aka bottom mean programming error. Thus catching them is debugging, bug hiding or something worse, but not exception handling. 100% agreed. The nice thing about the extensible exceptions is that you *can* decline to handle ErrorCall `exceptions'; but errors caught by try should be viewed analogously to signals or asynchronous exceptions. The RTS sometimes detects a bug and (sometimes!) stops execution with an exception; the user sometimes detects the bug and (sometimes!) stops execution with SIGINT. The most you can do is try to limit the amount of secondary damage and give the programmer the best clue where to start hunting. jcc ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Data Structures with Haskell
I am a beginner haskell programmer. I am interested in data structures implementation (all from basic ones like stack, queues etc. to advance ones like balanced binary trees, graphs etc.) in haskell. It would be really helpful if someone can point some good references for the same. Regards , Rohit ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Dan Weston wrote: So to be clear with the terminology: inductive = good consumer? coinductive = good producer? So fusion should be possible (automatically? or do I need a GHC rule?) with inductive . coinductive Or have I bungled it? Not quite. Induction means starting from base cases and building things upwards from those. Coinduction is the dual and can be thought of as starting from the ceiling and building your way downwards (until you hit the base cases, or possibly forever). So, if you have potentially infinite data (aka co-data) coming in, then you need to use coinduction because you may never see the basis but you want to make progress anyways. In formal terms, coinduction on co-data gives the same progress guarantees as induction on data, though termination is no longer a conclusion of progress (since coinduction may produce an infinite output from infinite input). Haskell doesn't distinguish data and co-data, but you can imagine data as if all the data constructors are strict, and co-data as if all the constructors are lazy. Another way to think of it is that finite lists (ala OCaml and SML) are data, but streams are co-data. For fusion there's the build/fold type and its dual unfold/destroy, where build/unfold are producers and fold/destroy are consumers. To understand how fusion works, let's look at the types of build and fold. GHC.Exts.build :: (forall b. (a - b - b) - b - b) - [a] flip (flip . foldr) :: [a] - ( (a - b - b) - b - b ) Together they give an isomorphism between lists as an ADT [a] and as a catamorphism (forall b. (a - b - b) - b - b), aka Church encoding. When we have build followed by foldr, we can remove the intermediate list and pass the F-algebra down directly: foldr cons nil (build k) = k cons nil For unfold/destroy fusion the idea is the same except that we use unfold (an anamorphism on the greatest fixed point) instead of fold (a catamorphism on the least fixed point). The two fixed points coincide in Haskell. Since Haskell does build/fold fusion, good producer requires that the function was written using build, and good consumer requires it's written using foldr. Using these functions allows us to apply the rule, though it's not sufficient for good fusion. Why the functions have the particular types they do and why this is safe has to do with induction and coinduction, but the relationship isn't direct. The reason a coinductive function is easy to make into a good producer has to do with that relationship. Take a canonically coinductive function like f [] = [] f (x:xs) = x : f xs Once we've made one step of recursion, we've generated (x:) and then have a thunk for recursing. Most importantly is that no matter how we evaluate the rest of the list, the head of the return value is already known to be (:) thus we can get to WHNF after one step. Whatever function is consuming this output can then take x and do whatever with it, and then pull on f xs which then takes a single step and returns (x':) along with a thunk f xs'. Because all of those (:) are being produced immediately, it's easy to abstract it out as a functional argument--- thus we can use build. Coinduction doesn't need to do 1-to-1 mapping of input to output, there just needs to be the guarantee that we only need to read a finite amount of input before producing a non-zero finite amount of output. These functions are also coinductive: p [] = [] p [x] = [x] p (x:y:ys) = y : x : p ys q [] = [] q [x] = [] q (x:y:ys) = y : q ys r [] = [] r (x:xs) = x : x : r xs They can also be written using build, though they're chunkier about reading input or producing output. These functions are not coinductive because there's no finite bound on how long it takes to reach WHNF: bad [] = [] bad (x:xs) = bad xs reverse [] = [] reverse (x:xs) = reverse xs ++ [x] Because build/fold is an isomorphism, we can technically use build for writing *any* function that produces a list. However, there's more to fusion than just using the build/fold isomorphism. The big idea behind it all is that when producers and consumers are in 1-to-1 correlation, then we can avoid allocating that 1 (the cons cell) and can just pass the arguments of the constructor directly to the consumer. For example: let buildF [] = [] buildF (x:xs) = x : buildF xs consumeF [] = 0 consumeF (x:xs) = 1 + consumeF xs in consumeF . buildF == let buildF = \xs - build (f xs) where f [] cons nil = nil f (x:xs) cons nil = x `cons` f xs cons nil consumeF = foldr consumeCons consumeNil where consumeNil = 0 consumeCons x rs = 1 + rs in consumeF . buildF == let f [] cons nil = nil f (x:xs) cons nil = x `cons` f xs
Re: [Haskell-cafe] Data Structures with Haskell
2009/3/25 Rohit Agrawalla son...@gmail.com: I am a beginner haskell programmer. I am interested in data structures implementation (all from basic ones like stack, queues etc. to advance ones like balanced binary trees, graphs etc.) in haskell. It would be really helpful if someone can point some good references for the same. Regards , Rohit Okasaki's thesis on functional datastructures http://www.cs.cmu.edu/~rwh/theses/okasaki.pdf and the implementation in Haskell http://hackage.haskell.org/cgi-bin/hackage-scripts/package/EdisonCore are both good places to start. -- gwern signature.asc Description: OpenPGP digital signature ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
On Wed, Mar 25, 2009 at 12:44 PM, Thomas Hartman tphya...@gmail.com wrote: Are you saying there's a problem with this implementation? It's the Yes, there is actually a problem with this implementation. However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. Well the problem here isn't that the code does something surprising. It's author was making assumptions about the type of input that it's going to get. I think that's an orthogonal issue. So... I insist... Easy for a beginner to read == better! Not at all. Beginner list processing code can and often does go awry when presented with infinite lists. The moral here has nothing to do with readability by beginners. It's: if the function you're defining could be extended naturally to infinite lists, and it would be useful to do so, then make it do so. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: about Haskell code written to be too smart
On Wed, Mar 25, 2009 at 8:25 AM, Jonathan Cast jonathancc...@fastmail.fm wrote: On Wed, 2009-03-25 at 15:09 +, Simon Marlow wrote: the ordering that the state monad expects (and I can never remember which way around they are in Control.Monad.State). Really? I found it obvious once I figured out it how simple it made (=). With the order from Control.Monad.State (with constructors ignored): a = f = \ s - case s a of (x, s') - f x s' Reversing the order of the components of the result gives you a = f = \ s - case s a of (s', x) - f x s' which just looks weird. However, if you are used to thinking in terms of type composition, s - (s, a) makes more sense, because it is effectively (s -) . (s,) . Identity whose functor-ness is automatic via composition of functors: newtype Identity a = Identity a inIdentity f (Identity a) = Identity (f a) instance Functor Identity where fmap f = inIdentity f instance Functor ((,) a) where fmap f (a, x) = (a, f x) instance Functor ((-) a) where fmap f k a = f (k a) newtype O f g x = O (f (g x)) inO f (O a) = O (f a) instance (Functor f, Functor g) = Functor (O f g) where fmap f = inO (fmap (fmap f)) -- or fmap = inO . fmap . fmap -- not valid haskell, but if there were sections at the type level it would be. type State s = (s -) `O` (s,) `O` Identity -- ryan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] [OT] Japanese (was: Re: about Haskell code written to be too smart)
Zachary Turner wrote: On Tue, Mar 24, 2009 at 10:32 PM, wren ng thornton w...@freegeek.orgwrote: Both of these conclusions seem quite natural to me, even from before learning Haskell. It seems, therefore, that naturality is not the proper metric to discuss. It's oft overlooked, but the fact is that expressivity comes not from more formal power, but from _less_. * Natural language has a limited range of words and syntactic constructs, but gives the larger-enough building blocks to enable unconstrained communication; whereas a language with a unique word for every utterance (arguably simpler) is impossible to learn. On the other hand, -certain- languages are more expressive than others. As an example, I personally find English far more expressive than both Vietnamese and Japanese, yet English is far more complicated. That's funny, I find Japanese to be far more expressive than English. (The language itself. Due to familiarity, I myself am more expressive in English.) Japanese has sophisticated forms of address that indicate the distance, degree, and style of the speaker's relationship with the listener. In English we can get the point across but we don't have the formalism and so it's all a lot more handwaving. Japanese can indicate topic and focus directly; whereas English must resort to bold/italics or syntactic contortions to be precise. Japanese has a wide assortment of pronouns which imply measures of respect, arrogance, disdain, abashment, etc; whereas English is limited to a small number that are only deictic. Japanese has many postpositions which capture abstract comparative relations that are difficult to express concisely in English. Japanese sentential particles can express a wide range of affect; whereas English must rely on intonation and context to determine whether something should be interpreted as compassionate, bonding, insulting, ironic, etc. Of course it all depends on what exactly you care to express. Japanese has restricted phonology, as you mentioned, though this is only as meaningful as the character set used for variable names in a programming language. Japanese also lacks certain sophisticated distinctions in English like definite vs indefinite articles, and singular vs plural vs mass-count nouns. Words that are spelled the same in Japanese are pronounced the same 100% of the time. False. There are numerous words which have the same spelling and different pronunciations. For example 今日 can be either /kyou/ today or /kon'niti/ every day; daily. This is one reason why learning to read Japanese is so difficult for westerners. An even bigger reason is that countless words can be spelled in a number of different ways, with each spelling having different nuances and implications (sometimes to the point where the spellings are not interchangeable). Anyway the point of all this is that in English you have more freedom and more power, and hence you use (abuse?) the syntax of the language to create words, sentences, and phrases that express very powerful things. Furthermore, they are things that almost all English speakers would be able to grasp the full meaning of what you've said. All natural languages are Thinking-complete. Just like with Turing-complete programming languages, the only difference is where they hide the bodies. There are plenty of things that I as a native speaker of English could say which other natives would grasp but which would confuse many of my non-native yet fluent coworkers. The Japanese abuse their syntax just as badly as we abuse English, or far far worse if we include the slang of youth culture. The Japanese have long thought of their language as a toy box ripe for experimentation, and you can see the effects of this everywhere. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: Data Structures with Haskell
Rohit Agrawalla son...@gmail.com wrote: I am a beginner haskell programmer. I am interested in data structures implementation (all from basic ones like stack, queues etc. to advance ones like balanced binary trees, graphs etc.) in haskell. It would be really helpful if someone can point some good references for the same. The fgl paper[1] is highly readable. It explains and solves the issues a functional approach has to overcome that an imperative approach can simply hack around and gave me many important insights into how to think in a functional way as I was starting to learn Haskell. YMMV, but if you're a decent imperative coder and/or got any kind of scheme or ocaml experience most of it shouldn't be too hard to follow. [1] http://web.engr.oregonstate.edu/~erwig/papers/abstracts.html#JFP01 -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: How to increment an Int in Haskell (stack overflow issue)
From: Tim Bauer bauer...@eecs.orst.edu I have a program that is currently blowing out the stack, Stack space overflow: current size 8388608 bytes. Use `+RTS -Ksize' to increase it. I am pretty sure I get to the end of the computation that increments various statistic counters (lazily?) and only when I go to print them out at the end, do things fail. In addition to the excellent advice provided by others on this topic, you may want to look at using GHC's heap profiler if you can't track down the source of a memory issue. I've found it helpful in the past. Keep in mind that there are several different modes that may or may not be helpful for a particular problem, so you should try them all to see if you get any useful information. John ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] Re: [OT] Japanese (was: Re: about Haskell code written to be too smart)
wren ng thornton w...@freegeek.org wrote: All natural languages are Thinking-complete. No, they aren't. Falsifying the Saphir-Worph thesis, I quite often find myself incapable of expressing a certain thought, or if I succeed, come up with two or more versions in multiple different languages that mean slightly different things, and, in retrospect, all don't fit the thought. On another scale, it's just a waste of time: Why should I spend minutes figuring out how to spell out Even though X - Y and X - nonsense, (Z - Y) - nonsense does not necessarily hold when I already figured that one out. All thoughts are fundamentally ineffable: Therefore, all languages are thinking-incomplete. -- (c) this sig last receiving data processing entity. Inspect headers for copyright history. All rights reserved. Copying, hiring, renting, performance and/or quoting of this signature prohibited. ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] about Haskell code written to be too smart
Beginner list processing code can and often does go awry when presented with infinite lists. I didn't mean code that a beginner would write, I mean code that would be easy to understand for a beginner to read -- that is, explicit pattern matching, explicit recursion, no gratuitous use of state monad. I don't think I necessarily would have written my favored version when learning haskell, probably something a lot uglier. What I like about the pattern matching is the totality -- you see all the possible inputs, and you see what happens. With the state version, there's a lot of behind-the-scenes magic, and as we've seen, things can go wrong. Also, the issue isn't infinite lists, but lists that are longer than the sum of the partitions provided. The state monad partition version goes equally as badly awry if the test is restructured as testP pf = mapM_ putStrLn [ show . pf ( take 1000 [3,7..] ) $ [1..10] , show . pf [3,7,11,15] $ ( take (10^6) [1..]) , show . head . last $ pf (take 1000 $ [3,3..]) [1..10^6] ] (no infinite lists, just long lists) 2009/3/25 Dan Piponi dpip...@gmail.com: On Wed, Mar 25, 2009 at 12:44 PM, Thomas Hartman tphya...@gmail.com wrote: Are you saying there's a problem with this implementation? It's the Yes, there is actually a problem with this implementation. However, there is something to be said for code that just looks like a duck and quacks like a duck. It's less likely to surprise you. Well the problem here isn't that the code does something surprising. It's author was making assumptions about the type of input that it's going to get. I think that's an orthogonal issue. So... I insist... Easy for a beginner to read == better! Not at all. Beginner list processing code can and often does go awry when presented with infinite lists. The moral here has nothing to do with readability by beginners. It's: if the function you're defining could be extended naturally to infinite lists, and it would be useful to do so, then make it do so. -- Dan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
Henning Thielemann wrote: Jonathan Cast wrote: Xiao-Yong Jin wrote: Could you elaborate more about why this kind of breakage wouldn't happen if 'try' is used in an IO monad as intended? It would. But it would happen in IO, which is allowed to be non-deterministic. Pure Haskell is not allowed to be non-deterministic. In my opinion, 'try' catching 'error's is still a hack, since 'error's aka bottom mean programming error. Thus catching them is debugging, bug hiding or something worse, but not exception handling. 'try' and friends should be limited to exceptional outcomes of IO actions, e.g. disk full, file read protected etc. There might be a variant 'unsafeTry' which can also block 'error's. +1. I have long been disappointed by a number of `error`s which shouldn't be. For example, the fact that `head` and `div` are not total strikes me as a (solvable) weakness of type checking, rather than things that should occur as programmer errors/exceptions at runtime. The use of `error` in these cases muddies the waters and leads to a laissez-faire attitude about when it's acceptable to throw one's hands up in despair and use `error` rather than writing a better function. As nice as exceptional control flow is, I can't help but think there was a reason the H98 committee said that `error` should be uncatchable. That we'd like to be able to catch errors in an interpreter or debugger is the exception that proves the rule. Extensible exceptions are impressive, but the existence of exceptions outside of type annotations says something about purity. Let us not err in the direction of Java, but we really should plug that hole. -- Live well, ~wren ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] typeOf for polymorphic value
Using Data.Typeable.typeOf we can get a representation of the the type of a monomorphic value, for instance Prelude Data.Typeable typeOf not Bool - Bool But if we try using it on a polymorphic value it fails Prelude Data.Typeable typeOf id interactive:1:0: Ambiguous type variable `a' in the constraint: `Typeable a' arising from a use of `typeOf' at interactive:1:0-8 Probable fix: add a type signature that fixes these type variable(s) And understandably so. Does anyone know of a trick to accomplish `typeOf id'? Using something else than TypeRep as the representation, of course. Any tricks and existing language extensions are welcome. (As ghc moves towards first class polymorphic values this question gets more interesting.) -- Lennart ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Learning Haskell
I'm still learning. :) (And I wrote the first available Haskell compiler.) -- Lennart On Tue, Mar 24, 2009 at 4:08 AM, Tom.Amundsen tomamund...@gmail.com wrote: How long did it take you to become proficient in Haskell? By that, I mean - how long until you were just as comfortable with Haskell as you were with your strongest language at that time? -- View this message in context: http://www.nabble.com/Learning-Haskell-tp22673552p22673552.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
[Haskell-cafe] Re: about Haskell code written to be too smart
Manlio Perillo wrote: Heinrich Apfelmus ha scritto: I think you'd have had a much easier time by starting with a proper book right away, like Richard Bird's Introduction to Functional Programming in Haskell, accompanied by Real World Haskell. Unfortunately, one year ago Real World Haskell was not here. And note that I have no problems with basic functional programming concepts. My problems are specific to Haskell. Despite the title, Bird's book is quite specific to Haskell, in particular concerning the philosophy of composing solutions from building blocks as opposed to primitive recursion. I'd say that every serious Haskell programmer should have it on his bookshelf (even if only for show ;) ). Regards, apfelmus -- http://apfelmus.nfshost.com ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Re: a cabal package with both a library and executable programs
On Wed, 2009-03-25 at 15:19 +0100, Achim Schneider wrote: Manlio Perillo manlio_peri...@libero.it wrote: Should I fill a feature request ticket, or this is how it is supposed to work? I would like to be able to do that, too. I also don't want cabal to recompile a thousand modules just for a demo program, and don't want to see hackage being polluted by thousands of foo-lib and foo-bin packages to circumvent the current behaviour, either. That is, feel yourself seconded. The existing ticket for this feature request is: http://hackage.haskell.org/trac/hackage/ticket/89 The plan is to allow the executables to build-depend on the library. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Wed, 2009-03-25 at 18:14 +0100, Benja Fallenstein wrote: On Wed, Mar 25, 2009 at 3:52 AM, Duncan Coutts Of course your tryArith only tests for certain kinds of _|_ value, but in principle the problem is the same. That's not *quite* how the semantics of Haskell exceptions are defined, actually, unless I'm misunderstanding something or the thinking about it has changed since the original paper on the topic: Yep, that's the semantics I've been working from too. I was not being precise when I said tests for _|_. As you point out, the semantics of imprecise exceptions distinguishes exceptions from bottom, however pure code cannot make that distinction and so that's why I was lumping them together and saying that tryArith tests for certain kinds of _|_ value. tryArith is still noncontinuous, though, and nondeterministic, too. Consider: Those are nice examples. Thanks for that. I was too tired to come up with any :-) Anyway, I hope this is enough to dissuade people from using unsafePerformIO to catch exceptions. Duncan ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Re: [Haskell-cafe] Use unsafePerformIO to catch Exception?
On Thu, Mar 26, 2009 at 2:40 AM, Duncan Coutts duncan.cou...@worc.ox.ac.uk wrote: I was not being precise when I said tests for _|_. As you point out, the semantics of imprecise exceptions distinguishes exceptions from bottom, however pure code cannot make that distinction and so that's why I was lumping them together and saying that tryArith tests for certain kinds of _|_ value. Right... I had this mental picture of exceptions being values denotationally smaller than any real value of the domain before I read the imprecise exceptions paper, so I interpreted your imprecise description that way =) Anyway, I hope this is enough to dissuade people from using unsafePerformIO to catch exceptions. Yes, unfortunately you can't even use it to return Nothing on errors (ie without returning the specific exception) because of the (overflow + loop) issue where you have nondeterminism between returning Nothing and looping forever. I have my own history of wondering why isn't there in Control.Exception a function that... for a while before figuring out why there isn't :-) - Benja ___ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
[Haskell-cafe] typeOf for polymorphic value
Does anyone know of a trick to accomplish `typeOf id'? Using something else than TypeRep as the representation, of course. Yes. The analysis of polymorphic types has been used in the inverse type-checker http://okmij.org/ftp/Haskell/types.html#de-typechecker The enclosed code computes TypeRep of polymorphic values. The code returns real TypeRep. Here are a few examples: tt2 = mytypof not -- Bool - Bool tt3 = mytypof [True] -- [Bool] tt4 = mytypof id -- any1 - any1 tt5 = mytypof [] -- [any1] tt6 = mytypof const -- any1 - any2 - any1 tt7 = mytypof Just -- any1 - Maybe any1 tt8 = mytypof map -- (any1 - any2) - [any1] - [any2] tt9 = mytypof maybe -- any1 - (any2 - any1) - Maybe any2 - any1 The code was tested on GHC 6.8.2. I don't have access to any computer with GHC 6.10, so I can't say how it works with that version of GHC. {-# LANGUAGE ScopedTypeVariables, EmptyDataDecls #-} {-# LANGUAGE FlexibleInstances, FlexibleContexts #-} {-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} {-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE OverlappingInstances #-} {-# LANGUAGE IncoherentInstances #-} module Typeof where import Data.Typeable -- tests tt1 = mytypof True -- Bool tt2 = mytypof not -- Bool - Bool tt3 = mytypof [True] -- [Bool] tt4 = mytypof id -- any1 - any1 tt5 = mytypof [] -- [any1] tt6 = mytypof const -- any1 - any2 - any1 tt7 = mytypof Just -- any1 - Maybe any1 tt8 = mytypof map -- (any1 - any2) - [any1] - [any2] tt9 = mytypof maybe -- any1 - (any2 - any1) - Maybe any2 - any1 class MyTypeable a where mytypof :: a - TypeRep -- Gamma is the sequence of type varaibles. It is used to assign -- different indices to different type variables instance (Analyze a result, MyTypeable' HNil gout result) = MyTypeable a where mytypof a = fst $ mytypof' HNil (analyze a) class MyTypeable' gin gout classification | gin classification - gout where mytypof' :: gin - classification - (TypeRep,gout) instance Typeable a = MyTypeable' gin gin (TAtomic a) where mytypof' gin _ = (typeOf (undefined::a), gin) instance Typeable a = MyTypeable' gin gin (TAtomic1 a) where mytypof' gin _ = (typeOf (undefined::a), gin) instance (MyTypeable' gin g a, MyTypeable' g gout b) = MyTypeable' gin gout (TFunction a b) where mytypof' gin _ = let (tr1,g)= mytypof' gin (undefined::a) (tr2,gout) = mytypof' g (undefined::b) in (mkFunTy tr1 tr2,gout) instance (MyTypeable' gin g c, MyTypeable' g gout a) = MyTypeable' gin gout (TConstructed c a) where mytypof' gin _ = let (tr1,g)= mytypof' gin (undefined::c) (tr2,gout) = mytypof' g (undefined::a) in (mkTyConApp (typeRepTyCon tr1) [tr2],gout) instance (HIndex a gin n, MyTypeable'' n gin gout (TVariable a)) = MyTypeable' gin gout (TVariable a) where mytypof' = mytypof'' (undefined::n) class MyTypeable'' n gin gout classification | n gin classification -gout where mytypof'' :: n - gin - classification - (TypeRep,gout) instance HLen gin n1 = MyTypeable'' Z gin (HCons a gin) (TVariable a) where mytypof'' _ gin _ = (mkany (undefined::S n1), HCons (undefined::a) gin) instance Nat n = MyTypeable'' (S n) gin gin (TVariable a) where mytypof'' _ gin _ = (mkany (undefined::S n), gin) mkany :: Nat n = n - TypeRep mkany n = mkTyConApp (mkTyCon ts) [] where ts = any ++ show (nat n) -- Lookup the index of an item x in the list l -- The index is 1-based. If not found, return 0 class Nat n = HIndex x l n | x l - n instance HIndex x HNil Z instance (Nat n, TypeEq x a f, HIndex' f x (HCons a l) n) = HIndex x (HCons a l) n class HIndex' f x l n | f x l - n instance HLen l n = HIndex' HTrue x l n instance HIndex x l n = HIndex' HFalse x (HCons a l) n -- Length of a list class Nat n = HLen l n | l - n instance HLen HNil Z instance HLen l n = HLen (HCons a l) (S n) -- Analyze a type -- Result of the type analysis data TAtomic a data TVariable a data TFunction a b data TConstructed c a -- only one level: kind * - * data TAtomic1 a data TVariable1 a data Level1 a data W a = W a -- We can have more levels, cf Typeable2, etc. class Analyze a b | a - b analyze:: Analyze a b = a - b analyze = undefined instance TypeCast f (TAtomic Int) = Analyze Int f instance TypeCast f (TAtomic Bool) = Analyze Bool f instance TypeCast f (TAtomic Char) = Analyze Char f instance TypeCast f (TAtomic Int) = Analyze (W Int) f instance TypeCast f (TAtomic Bool) = Analyze (W Bool) f instance TypeCast f (TAtomic Char) = Analyze (W Char) f instance (Analyze (c x) rx, Analyze (d y) ry, TypeCast f (TFunction rx ry)) = Analyze (c x-d y) f instance (Analyze (W x) rx, Analyze (d y) ry, TypeCast f (TFunction rx ry)) = Analyze (x-d y) f instance (Analyze (c x) rx, Analyze (W y) ry, TypeCast f (TFunction rx ry)) = Analyze (c x-y) f instance (Analyze (W x) rx, Analyze