map increases length of list

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

map increases length of list

Aaron MacDonald
For some reason, the map function returns a list that has one more  
element than my input list.

My input list is a range defined by [0, 60..359] (should translate  
into [0,60,120,180,240,300]).

The function I'm giving to map is defined this way:
-----
degreesToRadians :: Double -> Double
degreesToRadians degrees = degrees * (pi / 180)
-----

This is how I'm calling map overall:
-----
 > map degreesToRadians [0,60..359]
[0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586
]
-----

As you can hopefully see, there are seven elements instead of six.  
Getting the length confirms this:
-----
 > length [0,60..359]
6
 > length $ map degreesToRadians [0,60..359]
7
-----

I do not seem to get this behaviour with the length if I either  
substitute the degreesToRadians function or substitute the [0,60..359]  
range.

P.S. Is there a built-in function to convert degrees to radians and  
vice-versa?
Reply | Threaded
Open this post in threaded view
|

map increases length of list

Henk-Jan van Tuyl
On Wed, 17 Jun 2009 23:35:23 +0200, Aaron MacDonald <[hidden email]>  
wrote:

>
> This is how I'm calling map overall:
> -----
>  > map degreesToRadians [0,60..359]
> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586
> ]
> -----
>
> As you can hopefully see, there are seven elements instead of six.  
> Getting the length confirms this:
> -----
>  > length [0,60..359]
> 6
>  > length $ map degreesToRadians [0,60..359]
> 7
> -----

Enumeration works differently for Double:
   Prelude> [0, 60..359 :: Double]
   [0.0,60.0,120.0,180.0,240.0,300.0,360.0]
   Prelude> length [0, 60..359 :: Double]
   7


--
Met vriendelijke groet,
Henk-Jan van Tuyl


--
http://functor.bamikanarie.com
http://Van.Tuyl.eu/
--


Reply | Threaded
Open this post in threaded view
|

map increases length of list

Michael Snoyman
In reply to this post by Aaron MacDonald
Aaron,

Look at the following snippet:

> length ([0,60..359] :: [Double])
7

Basically, the Enum instance for Double is done differently than for Int (I
don't remember why exactly). If you take off the type signature, it uses Int
by default. When you use map, it implicitly converts that to a Double.

Hope that helps.

Michael

On Thu, Jun 18, 2009 at 12:35 AM, Aaron MacDonald <[hidden email]>wrote:

> For some reason, the map function returns a list that has one more element
> than my input list.
>
> My input list is a range defined by [0, 60..359] (should translate into
> [0,60,120,180,240,300]).
>
> The function I'm giving to map is defined this way:
> -----
> degreesToRadians :: Double -> Double
> degreesToRadians degrees = degrees * (pi / 180)
> -----
>
> This is how I'm calling map overall:
> -----
> > map degreesToRadians [0,60..359]
>
> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586]
> -----
>
> As you can hopefully see, there are seven elements instead of six. Getting
> the length confirms this:
> -----
> > length [0,60..359]
> 6
> > length $ map degreesToRadians [0,60..359]
> 7
> -----
>
> I do not seem to get this behaviour with the length if I either substitute
> the degreesToRadians function or substitute the [0,60..359] range.
>
> P.S. Is there a built-in function to convert degrees to radians and
> vice-versa?
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090617/cc915786/attachment.html
Reply | Threaded
Open this post in threaded view
|

map increases length of list

Aaron MacDonald
In reply to this post by Henk-Jan van Tuyl
Sigh.

Well, what I was trying to do was get all angles in the range [0, 360)  
that have 60 degrees between them, since I'm going to be working with  
hexagons.  I figured I'd use a range instead of hard-coded angles in  
case I wanted to use other shapes.

Thanks,

Aaron

On 17-Jun-09, at 6:58 PM, Henk-Jan van Tuyl wrote:

> On Wed, 17 Jun 2009 23:35:23 +0200, Aaron MacDonald <[hidden email]
> > wrote:
>
>>
>> This is how I'm calling map overall:
>> -----
>> > map degreesToRadians [0,60..359]
>> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586
>> ]
>> -----
>>
>> As you can hopefully see, there are seven elements instead of six.  
>> Getting the length confirms this:
>> -----
>> > length [0,60..359]
>> 6
>> > length $ map degreesToRadians [0,60..359]
>> 7
>> -----
>
> Enumeration works differently for Double:
>  Prelude> [0, 60..359 :: Double]
>  [0.0,60.0,120.0,180.0,240.0,300.0,360.0]
>  Prelude> length [0, 60..359 :: Double]
>  7
>
>
> --
> Met vriendelijke groet,
> Henk-Jan van Tuyl
>
>
> --
> http://functor.bamikanarie.com
> http://Van.Tuyl.eu/
> --
>
>

Reply | Threaded
Open this post in threaded view
|

map increases length of list

Alan Mock
In reply to this post by Aaron MacDonald
That's because [0,60,..359] is not the same as [0,60..359] ::  
[Double].  So what you're passing to degreesToRadians is  
[0.0,60.0,120.0,180.0,240.0,300.0,360.0] and not  
[0,60,120,180,240,300].  I don't know why the Double version adds  
another number, though.

On Jun 17, 2009, at 4:35 PM, Aaron MacDonald wrote:

> For some reason, the map function returns a list that has one more  
> element than my input list.
>
> My input list is a range defined by [0, 60..359] (should translate  
> into [0,60,120,180,240,300]).
>
> The function I'm giving to map is defined this way:
> -----
> degreesToRadians :: Double -> Double
> degreesToRadians degrees = degrees * (pi / 180)
> -----
>
> This is how I'm calling map overall:
> -----
> > map degreesToRadians [0,60..359]
> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586
> ]
> -----
>
> As you can hopefully see, there are seven elements instead of six.  
> Getting the length confirms this:
> -----
> > length [0,60..359]
> 6
> > length $ map degreesToRadians [0,60..359]
> 7
> -----
>
> I do not seem to get this behaviour with the length if I either  
> substitute the degreesToRadians function or substitute the  
> [0,60..359] range.
>
> P.S. Is there a built-in function to convert degrees to radians and  
> vice-versa?
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners

Reply | Threaded
Open this post in threaded view
|

map increases length of list

I. J. Kennedy
I think I understand the reason why, but still I find it disturbing that in
this first expression, x has 6 elements:

Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map degreesToRadians
y)
([0,60,120,180,240,300],[0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,1.0471975333333332,2.094395066
6666664,3.1415926,4.188790133333333,5.235987666666667,6.2831852])

But if I add a comparison to y, x now has 7 elements:

Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map degreesToRadians
y, *x==y*)
([0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,1.0471975333
333332,2.0943950666666664,3.1415926,4.188790133333333,5.235987666666667,6.2831852],True)

I. J. Kennedy


On Wed, Jun 17, 2009 at 4:55 PM, Alan Mock <[hidden email]> wrote:

> That's because [0,60,..359] is not the same as [0,60..359] :: [Double].  So
> what you're passing to degreesToRadians is
> [0.0,60.0,120.0,180.0,240.0,300.0,360.0] and not [0,60,120,180,240,300].  I
> don't know why the Double version adds another number, though.
>
>
> On Jun 17, 2009, at 4:35 PM, Aaron MacDonald wrote:
>
>  For some reason, the map function returns a list that has one more element
>> than my input list.
>>
>> My input list is a range defined by [0, 60..359] (should translate into
>> [0,60,120,180,240,300]).
>>
>> The function I'm giving to map is defined this way:
>> -----
>> degreesToRadians :: Double -> Double
>> degreesToRadians degrees = degrees * (pi / 180)
>> -----
>>
>> This is how I'm calling map overall:
>> -----
>> > map degreesToRadians [0,60..359]
>>
>> [0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586]
>> -----
>>
>> As you can hopefully see, there are seven elements instead of six. Getting
>> the length confirms this:
>> -----
>> > length [0,60..359]
>> 6
>> > length $ map degreesToRadians [0,60..359]
>> 7
>> -----
>>
>> I do not seem to get this behaviour with the length if I either substitute
>> the degreesToRadians function or substitute the [0,60..359] range.
>>
>> P.S. Is there a built-in function to convert degrees to radians and
>> vice-versa?
>> _______________________________________________
>> Beginners mailing list
>> [hidden email]
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
> _______________________________________________
> Beginners mailing list
> [hidden email]
> http://www.haskell.org/mailman/listinfo/beginners
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: http://www.haskell.org/pipermail/beginners/attachments/20090618/32f60c05/attachment.html
Reply | Threaded
Open this post in threaded view
|

map increases length of list

Daniel Fischer-4
Am Donnerstag 18 Juni 2009 15:24:20 schrieb Jack Kennedy:
> I think I understand the reason why, but still I find it disturbing that in
> this first expression, x has 6 elements:
>
> Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map
> degreesToRadians y)

You give no type for x, so the default is chosen, that is Integer.
The expression map degreesToRadians y forces y to have type [Double] (you could give y a
more general type if you specified a type signature).

> ([0,60,120,180,240,300],[0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,1.047
>1975333333332,2.094395066
> 6666664,3.1415926,4.188790133333333,5.235987666666667,6.2831852])
>
> But if I add a comparison to y, x now has 7 elements:
>
> Prelude> let x = [0,60..359]; y = [0,60..359] in (x, y, map
> degreesToRadians y, *x==y*)
> ([0.0,60.0,120.0,180.0,240.0,300.0,360.0],[0.0,60.0,120.0,180.0,240.0,300.0
>,360.0],[0.0,1.0471975333
> 333332,2.0943950666666664,3.1415926,4.188790133333333,5.235987666666667,6.2
>831852],True)

Now, the expression x==y forces x to have the same type as y, which still is [Double].

But, lo and behold:
Prelude> let degreesToRadians :: Double -> Double; degreesToRadians d = d*pi/180
Prelude> let x :: (Num a, Enum a) => [a]; x = [0, 60 .. 359]; y :: (Num a, Enum a) => [a];
y = [0, 60 .. 359]
Prelude> (x,y,map degreesToRadians y, x == y)
([0,60,120,180,240,300],[0,60,120,180,240,300],
[0.0,1.0471975511965976,2.0943951023931953,3.141592653589793,4.1887902047863905,5.235987755982989,6.283185307179586],True)


>
> I. J. Kennedy
>

Aai
Reply | Threaded
Open this post in threaded view
|

map increases length of list

Aai
Check this out:

Prelude> [0,60..330]::[Double]
[0.0,60.0,120.0,180.0,240.0,300.0,360.0]

Prelude> [0,60..329]::[Double]
[0.0,60.0,120.0,180.0,240.0,300.0]

It looks like the decision the step to the next value in case of flt.
point enumeration depends on >= enumWith / 2. But that should be
answered by those who know from under the hood.

--
Met vriendelijke groet,
=@@i

Reply | Threaded
Open this post in threaded view
|

map increases length of list

Brent Yorgey-2
On Thu, Jun 18, 2009 at 05:32:26PM +0200, Aai wrote:

> Check this out:
>
> Prelude> [0,60..330]::[Double]
> [0.0,60.0,120.0,180.0,240.0,300.0,360.0]
>
> Prelude> [0,60..329]::[Double]
> [0.0,60.0,120.0,180.0,240.0,300.0]
>
> It looks like the decision the step to the next value in case of flt.
> point enumeration depends on >= enumWith / 2. But that should be
> answered by those who know from under the hood.

That is correct.  The reason for this is because of the inaccuracy of
floating point numbers.  For example, consider

  [0.1,0.2..10.0]

which clearly ought to contain 100 numbers, every tenth from 0.1
through 10.0 inclusive. But 0.1 cannot be represented exactly in
binary, so adding 0.1 to itself 100 times might very well give a
result like 10.0000000002.  Should this be included in the range, or
not?  After all, it's bigger than 10.0...but it would be quite
surprising if the 10.0000000002 were left out.  Hence the last number
is included even if it is up to 1/2 of a step over the end value of
the range.  But this can also be surprising at times (as the original
poster found out!).  What to do?

The answer is: don't use list enumerations for floating point
numbers!!  It is nonsensical.  Alternative options include:

  * use Rational instead of Double, which IS exact
  * use Integers for the enumeration, and then convert to Double

and so on.

-Brent