Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Similar Haskell list comprehensions with different results

I don't understand why these two similar list comprehensions give different results:

Prelude> let t2s n= [ 1/(2*i) | i <- [1,3..n]]
Prelude> t2s 0
[0.5]
Prelude> let t2s n= [   (2*i) | i <- [1,3..n]]
Prelude> t2s 0
[]

I expected both to return [] on argument 0. I must be missing something silly?!

like image 580
guthrie Avatar asked Feb 22 '13 03:02

guthrie


2 Answers

First of all, I changed the name of your first t2s to t1s, so that I can have them both loaded into ghci at the same time. Look at the inferred types for each of them:

[ts.hs:2:1-33] *Main> :t t1s
t1s :: (Enum t, Fractional t) => t -> [t]
[ts.hs:2:1-33] *Main> :t t2s
t2s :: (Enum t, Num t) => t -> [t]
[ts.hs:2:1-33] *Main>

Note that t1s takes a Fractional argument whereas t2s takes a Num. This means that in t1s 0, the 0 is inferred to be a Double. On the other hand, the interpreter infers 0 to be a Integer in t2s 0. Since the type used for the argument differs, the behavior can differ in very surprising ways. In particular, you should be sure to use only Integral types when enumerating a list as in [1,3..n].

To fix this, you simply need to provide explicit type signatures for both functions.

like image 68
Code-Apprentice Avatar answered Oct 24 '22 06:10

Code-Apprentice


It has to do with the fact that

enumFromThenTo 1.0 3.0 0.0

evaluates to [1.0]. The specification of enumFromThenTo for Floats can be found in section 6.3.4 of http://www.haskell.org/onlinereport/haskell2010/haskellch6.html .

like image 6
Theodore Norvell Avatar answered Oct 24 '22 07:10

Theodore Norvell