Learn You a Haskell! I have a few questions!

Hi there to you all! I've been reading through the first chapter of "Learn You a Haskell" and I'd like to ask the community a few questions. Any help would be appreciated... -- ---------- ---------- ---------- ---------- ---------- All the standard Prelude functions that throw out an error when fed the []! head maximum ... Are there safe versions anywhere, or do we have to define them ourselves? -- ---------- ---------- ---------- ---------- ---------- This one is really important! I understand that for the definition of product to work as it is: product [] must be equal to 1 But what if we want to add a product to something else??? Shouldn't the result be Nothing? (I guess we would have to guard against this! But we must guard against the parameter of product being the empty list, anyway. Otherwise we risk adding 1 when there is nothing do multiply) (The same question arises with the functions and and or, and their boolean results, I think! Right?) -- ---------- ---------- ---------- ---------- ---------- -- ---------- Start Quote Names can't be enumerated. What comes after "John"? I don't know. -- ---------- End Quote "a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings? -- ---------- ---------- ---------- ---------- ---------- -- ---------- Start Quote To make a list with all the numbers from 20 to 1, you can't just do [20..1], you have to do [20,19..1]. -- ---------- End Quote Why is this? If the first was greater than the second it would just subtract! Right? -- ---------- ---------- ---------- ---------- ---------- -- ---------- Start Quote Watch out when using floating point numbers in ranges! Because they are not completely precise (by definition), their use in ranges can yield some pretty funky results. ghci> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999] -- ---------- End Quote Can anyone explain me why it works for the first few values, and not "completely"? -- ---------- ---------- ---------- ---------- ---------- Any thoughts? Thank You Very Much in advance! Gilberto

Am 18.04.2014 21:26 schrieb "Gilberto Melfe"
-- ---------- Start Quote
Names can't be enumerated. What comes after "John"? I don't know.
-- ---------- End Quote
"a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings?
Following your theory the next "name" would be "Joho", is that a name or just random letters? That's why you don't have predecessor or successor functions on String.
-- ---------- Start Quote
To make a list with all the numbers from 20 to 1, you can't just do [20..1], you have to do [20,19..1].
-- ---------- End Quote
Why is this? If the first was greater than the second it would just subtract! Right?
-- ---------- Start Quote
Watch out when using floating point numbers in ranges! Because they are not completely precise (by definition), their use in ranges can yield some
I would be with you, but that's not how it is designed. We can't change the given behavior. pretty funky results.
ghci> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
-- ---------- End Quote
Can anyone explain me why it works for the first few values, and not
"completely"? To explain that we had to go into how floating point numbers are represented internally in the PCs memory, I'm to tired to do that right now. But problems comparable to this one exist on every language that has floating point numbers. HTH Norbert

On 4/18/2014 2:38 PM, Norbert Melzer wrote:
"a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings?
Following your theory the next "name" would be "Joho", is that a name or just random letters? That's why you don't have predecessor or successor functions on String.
That's how it works in Perl. perl -e "$x='John'; ++$x; print $x; " produces "Joho" It would be an interesting beginner's exercise to implement that in Haskell (re: http://perldoc.perl.org/perlop.html#Auto-increment-and-Auto-decrement ) A foldr would be good, I suppose, but complicated by the need to return the carry state as well as the accumulated tail to the next iteration.

On Fri, Apr 18, 2014 at 8:12 AM, Gilberto Melfe
Hi there to you all!
I've been reading through the first chapter of "Learn You a Haskell" and I'd like to ask the community a few questions.
Any help would be appreciated...
-- ---------- ---------- ---------- ---------- ----------
All the standard Prelude functions that throw out an error when fed the []!
head maximum ...
Are there safe versions anywhere, or do we have to define them ourselves?
Not so many that ship with GHC or Haskell Platform, but you can install safe: https://hackage.haskell.org/package/safe Some of these you can work around, for example you can get a safe version of `head` just by using Data.Maybe.listToMaybe
-- ---------- ---------- ---------- ---------- ----------
This one is really important!
I understand that for the definition of product to work as it is: product [] must be equal to 1
But what if we want to add a product to something else??? Shouldn't the result be Nothing? (I guess we would have to guard against this! But we must guard against the parameter of product being the empty list, anyway. Otherwise we risk adding 1 when there is nothing do multiply)
(The same question arises with the functions and and or, and their boolean results, I think! Right?)
There's a precedent in mathematics for behaving like this. 0! and n^0 are both equal to 1 for example. It sounds like perhaps you're trying to do something strange with products of lists, and there might be a better way but it's hard to suggest something without a concrete example.
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
Names can't be enumerated. What comes after "John"? I don't know.
-- ---------- End Quote
"a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings?
This is not hard to implement, but you don't know which of those strings are names.
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
To make a list with all the numbers from 20 to 1, you can't just do [20..1], you have to do [20,19..1].
-- ---------- End Quote
Why is this? If the first was greater than the second it would just subtract! Right?
[a..b] is syntax sugar for enumFromTo and the definition of that function just doesn't behave in that way. [a, b .. c] is syntax sugar for enumFromThenTo which does. A reason for it to behave like this would be that it's often desired to have the behavior that it does. Consider enumerating every index in a list `xs` except for the first, you could write this as `[1 .. length xs - 1]` with the current syntax, but that sort of thing would yield surprising results if it sometimes went backwards.
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
Watch out when using floating point numbers in ranges! Because they are not completely precise (by definition), their use in ranges can yield some pretty funky results.
ghci> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
-- ---------- End Quote
Can anyone explain me why it works for the first few values, and not "completely"?
It doesn't "work" for any of the values, it's just an artifact of how they're rendered. 0.1 can't be exactly represented in binary floating point, so the error compounds. Double probably shouldn't be enumerable in the first place, but that's a decision we have to live with. The reason that the end result is so surprising is that 1.0999999999999999 is less than 1 + 0.1 and for whatever reason the way Enum is defined for Double checks to see if the result is > to+(then-from) rather than <= to.

On Fri, Apr 18, 2014 at 12:42 PM, Bob Ippolito
On Fri, Apr 18, 2014 at 8:12 AM, Gilberto Melfe
wrote: Hi there to you all!
I've been reading through the first chapter of "Learn You a Haskell" and I'd like to ask the community a few questions.
Any help would be appreciated...
-- ---------- ---------- ---------- ---------- ----------
All the standard Prelude functions that throw out an error when fed the []!
head maximum ...
Are there safe versions anywhere, or do we have to define them ourselves?
Not so many that ship with GHC or Haskell Platform, but you can install safe: https://hackage.haskell.org/package/safe
Some of these you can work around, for example you can get a safe version of `head` just by using Data.Maybe.listToMaybe
-- ---------- ---------- ---------- ---------- ----------
This one is really important!
I understand that for the definition of product to work as it is: product [] must be equal to 1
But what if we want to add a product to something else??? Shouldn't the result be Nothing? (I guess we would have to guard against this! But we must guard against the parameter of product being the empty list, anyway. Otherwise we risk adding 1 when there is nothing do multiply)
(The same question arises with the functions and and or, and their boolean results, I think! Right?)
There's a precedent in mathematics for behaving like this. 0! and n^0 are both equal to 1 for example. It sounds like perhaps you're trying to do something strange with products of lists, and there might be a better way but it's hard to suggest something without a concrete example.
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
Names can't be enumerated. What comes after "John"? I don't know.
-- ---------- End Quote
"a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings?
This is not hard to implement, but you don't know which of those strings are names.
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
To make a list with all the numbers from 20 to 1, you can't just do [20..1], you have to do [20,19..1].
-- ---------- End Quote
Why is this? If the first was greater than the second it would just subtract! Right?
[a..b] is syntax sugar for enumFromTo and the definition of that function just doesn't behave in that way. [a, b .. c] is syntax sugar for enumFromThenTo which does. A reason for it to behave like this would be that it's often desired to have the behavior that it does. Consider enumerating every index in a list `xs` except for the first, you could write this as `[1 .. length xs - 1]` with the current syntax, but that sort of thing would yield surprising results if it sometimes went backwards.
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
Watch out when using floating point numbers in ranges! Because they are not completely precise (by definition), their use in ranges can yield some pretty funky results.
ghci> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
-- ---------- End Quote
Can anyone explain me why it works for the first few values, and not "completely"?
It doesn't "work" for any of the values, it's just an artifact of how they're rendered. 0.1 can't be exactly represented in binary floating point, so the error compounds. Double probably shouldn't be enumerable in the first place, but that's a decision we have to live with. The reason that the end result is so surprising is that 1.0999999999999999 is less than 1 + 0.1 and for whatever reason the way Enum is defined for Double checks to see if the result is > to+(then-from) rather than <= to.
To clarify, this is what is happening: λ> takeWhile (< 1 + 0.1) $ iterate (+0.1) 0.1 [0.1,0.2,0.30000000000000004,0.4,0.5,0.6,0.7,0.7999999999999999,0.8999999999999999,0.9999999999999999,1.0999999999999999]

On Fri, Apr 18, 2014 at 12:54:48PM -0700, Bob Ippolito wrote:
ghci> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
-- ---------- End Quote
Can anyone explain me why it works for the first few values, and not "completely"?
It doesn't "work" for any of the values, it's just an artifact of how they're rendered. 0.1 can't be exactly represented in binary floating point, so the error compounds. Double probably shouldn't be enumerable in the first place, but that's a decision we have to live with. The reason that the end result is so surprising is that 1.0999999999999999 is less than 1 + 0.1 and for whatever reason the way Enum is defined for Double checks to see if the result is > to+(then-from) rather than <= to.
To clarify, this is what is happening:
λ> takeWhile (< 1 + 0.1) $ iterate (+0.1) 0.1
[0.1,0.2,0.30000000000000004,0.4,0.5,0.6,0.7,0.7999999999999999,0.8999999999999999,0.9999999999999999,1.0999999999999999]
Actually, the check is whether the result is > to + ((then - from)/2). Notice that the original example is stepping by 0.2, not 0.1. -Brent

Are there safe versions anywhere, or do we have to define them ourselves?
There are some in the safe package. Also some prelude replacements like basic-prelude or classy-prelude that have their own renditions versions of some functions.
(The same question arises with the functions and and or, and their boolean results, I think! Right?)
Product works for empty lists because 1 is a sensible answer and returning maybe is cumbersome, so it does the sensible thing. There are many times where I use any or all and I want it to work for empty lists rather than having to make my own version. This same goes for sum.
"a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings?
It is possible, but what should the successor to "john" be? Should it be "johN" or "joho"? If there is more than one way to do a thing, it is better to leave the instance off and allow the user to specify his order in his own application. You can see such api design decisions come to the forefront in some modules like Data.Monoid where it could interpret integers as monoids over sums, products, or a multitude of other ways.
To make a list with all the numbers from 20 to 1, you can't just do [20..1], you have to do [20,19..1].
It is that way because [20..1] desugars to enumFromTo 20 1, which chose to do it that way. Personally I'd be all for the change, but people have come to depend on the way it is now, and so it is possible that code would break if they changed it.
Can anyone explain me why it works for the first few values, and not "completely"?
The problem with enumerating floats is that floats don't actually represent
whole numbers well. On the hardware level there is a lot of fudging
involved. A lot of people think that having an enum instance for float is
a bad thing, but it is kept around because it can be useful sometimes. I
actually agree with those people.
On Fri, Apr 18, 2014 at 11:12 AM, Gilberto Melfe
Hi there to you all!
I've been reading through the first chapter of "Learn You a Haskell" and I'd like to ask the community a few questions.
Any help would be appreciated...
-- ---------- ---------- ---------- ---------- ----------
All the standard Prelude functions that throw out an error when fed the []!
head maximum ...
Are there safe versions anywhere, or do we have to define them ourselves?
-- ---------- ---------- ---------- ---------- ----------
This one is really important!
I understand that for the definition of product to work as it is: product [] must be equal to 1
But what if we want to add a product to something else??? Shouldn't the result be Nothing? (I guess we would have to guard against this! But we must guard against the parameter of product being the empty list, anyway. Otherwise we risk adding 1 when there is nothing do multiply)
(The same question arises with the functions and and or, and their boolean results, I think! Right?)
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
Names can't be enumerated. What comes after "John"? I don't know.
-- ---------- End Quote
"a" to "z" then "aa" to "zz" then "aaa" to "zzz" and so on! Is it to difficult or impossible to create a function that enumerates all possible strings?
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
To make a list with all the numbers from 20 to 1, you can't just do [20..1], you have to do [20,19..1].
-- ---------- End Quote
Why is this? If the first was greater than the second it would just subtract! Right?
-- ---------- ---------- ---------- ---------- ----------
-- ---------- Start Quote
Watch out when using floating point numbers in ranges! Because they are not completely precise (by definition), their use in ranges can yield some pretty funky results.
ghci> [0.1, 0.3 .. 1] [0.1,0.3,0.5,0.7,0.8999999999999999,1.0999999999999999]
-- ---------- End Quote
Can anyone explain me why it works for the first few values, and not "completely"?
-- ---------- ---------- ---------- ---------- ----------
Any thoughts?
Thank You Very Much in advance!
Gilberto
_______________________________________________ Beginners mailing list Beginners@haskell.org http://www.haskell.org/mailman/listinfo/beginners
participants (6)
-
Bob Ippolito
-
Brent Yorgey
-
David McBride
-
Gilberto Melfe
-
John M. Dlugosz
-
Norbert Melzer