Execution order of list comprehension filtering - haskell

Just started learning Haskell and came across this issue.
If I have a list comprehension with a condition such as
[x*2 | x<- [1..10], x `mod` 3 ==2]
I get
[4,10,16]
as expected. However, if I have instead
[x**2 | x<- [1..10], x `mod` 3 ==2]
It is has the type variable as ambiguous for the mod function. I presume this is because x2 promotes an integer to a float, but why does this affect the conditional? Why is the type ambiguous in this case? Does it calculate x2, and then square root it? (This seems highly improbable) Does it somehow keep track of the x that generated each x2 term?
Perhaps it's the imperative mindset, but internally, I thought the execution would be along the lines of [in python]
lst=[]
for x in range(10):
if x%3==2:
lst.append(x**2)
Could someone clarify/correct my understanding?

Let's have a look at the types of mod and (**):
mod :: Integral n => n -> n -> n
(**) :: Floating a => a -> a -> a
-- hm......
mod and (**) put other constraints on the used type. mod expects an integral type (Int, Integer), whereas (**) expects a floating type (Float, Double). Since there's no type that's both integral and a floating point number, GHC gives up.
Instead, use (^):
(^) :: (Integral n, Num a) => a -> n -> a
E.g.
[x ^ 2 | x <- [1..10], x `mod` 3 == 2]
By the way, you can find errors like this easier if you try to give a type to the result:
ghci> [x ** 2 | x <- [1..10], x `mod` 3 == 2] :: [Int]
<interactive>:1:4:
No instance for (Floating Int) arising from a use of `**'
In the expression: x ** 2
...

The first example works because of defaulting. The expression is inferred as having type
Integral a => [a]
and then the a type variable is defaulted to Integer for convenience.
In the second expression, the use of ** forces x to be Floating and the mod forces it to be Integral. So GHC infers that the expression has type
(Integral a, Floating a) => [a]
There is no standard numeric type that is both Integral and Floating, let alone one that participates in defaulting.
You mentioned the notion of numeric promotion in your question. C, C++, Java, and maybe some other languages have such a thing. Haskell does not, and those of us who use it tend to be grateful for that. All conversions from one numeric type to another have to be done using explicit conversion functions like fromIntegral, fromRational, round, floor, %, etc.
You probably meant to use ^ instead of **, which would leave just the Integral a constraint. In a real program, you should generally avoid the defaulting mechanism by including a type signature. You can turn it off altogether using
default ()
somewhere in your module.

List comprehension in haskell desugars to a do-block using the list monad. In your example, it would be something like:
x <- [1..10]
guard $ (x `mod` 3) == 2
return $ x**2
In this case it attempts to unify the types of (**) x 2 and mod x 3 which fails because you can't unify a Floating type with an Integral type without explicitly converting between the two.
You've got a few options: use (^^) instead of (**) or do ((fromIntegral x) ** 2) if you want x to be an integral type, or somehow round x to an integral type if you want it to be a floating type.

Related

Why does ghc warn that ^2 requires "defaulting the constraint to type 'Integer'?

If I compile the following source file with ghc -Wall:
main = putStr . show $ squareOfSum 5
squareOfSum :: Integral a => a -> a
squareOfSum n = (^2) $ sum [1..n]
I get:
powerTypes.hs:4:18: warning: [-Wtype-defaults]
• Defaulting the following constraints to type ‘Integer’
(Integral b0) arising from a use of ‘^’ at powerTypes.hs:4:18-19
(Num b0) arising from the literal ‘2’ at powerTypes.hs:4:19
• In the expression: (^ 2)
In the expression: (^ 2) $ sum [1 .. n]
In an equation for ‘squareOfSum’:
squareOfSum n = (^ 2) $ sum [1 .. n]
|
4 | squareOfSum n = (^2) $ sum [1..n]
| ^^
I understand that the type of (^) is:
Prelude> :t (^)
(^) :: (Integral b, Num a) => a -> b -> a
which means it works for any a^b provided a is a Num and b is an Integral. I also understand the type hierarchy to be:
Num --> Integral --> Int or Integer
where --> denotes "includes" and the first two are typeclasses while the last two are types.
Why does ghc not conclusively infer that 2 is an Int, instead of "defaulting the constraints to Integer". Why is ghc defaulting anything? Is replacing 2 with 2 :: Int a good way to resolve this warning?
In Haskell, numeric literals have a polymorphic type
2 :: Num a => a
This means that the expression 2 can be used to generate a value in any numeric type. For instance, all these expression type-check:
2 :: Int
2 :: Integer
2 :: Float
2 :: Double
2 :: MyCustomTypeForWhichIDefinedANumInstance
Technically, each time we use 2 we would have to write 2 :: T to choose the actual numeric type T we want. Fortunately, this is often not needed since type inference can frequently deduce T from the context. E.g.,
foo :: Int -> Int
foo x = x + 2
Here, x is an Int because of the type annotation, and + requires both operands to have the same type, hence Haskell infers 2 :: Int. Technically, this is because (+) has type
(+) :: Num a => a -> a -> a
Sometimes, however, type inference can not deduce T from the context. Consider this example involving a custom type class:
class C a where bar :: a -> String
instance C Int where bar x = "Int: " ++ show x
instance C Integer where bar x = "Integer: " ++ show x
test :: String
test = bar 2
What is the value of test? Well, if 2 is an Int, then we have test = "Int: 2". If it is an Integer, then we have test = "Integer: 2". If it's another numeric type T, we can not find an instance for C T.
This code is inherently ambiguous. In such a case, Haskell mandates that numeric types that can not be deduced are defaulted to Integer (the programmer can change this default to another type, but it's not relevant now). Hence we have test = "Integer: 2".
While this mechanism makes our code type check, it might cause an unintended result: for all we know, the programmer might have wanted 2 :: Int instead. Because of this, GHC chooses the default, but warns about it.
In your code, (^) can work with any Integral type for the exponent. But, in principle, x ^ (2::Int) and x ^ (2::Integer) could lead to different results. We know this is not the case since we know the semantics of (^), but for the compiler (^) is only a random function with that type, which could behave differently on Int and Integer. Consider, e.g.,
a ^ n = if n + 3000000000 < 0 then 0 else 1
When n = 2, if we use n :: Int the if guard could be true on a 32 bit system. This is not the case when using n :: Integer which never overflows.
The standard solution, in these cases, is to resolve the warning using something like x ^ (2 :: Int).

Convert Num to Doublle in Haskell

I am trying to write a function that calculates the average of the values of a list containing type Num.
Here is what I tried:
mean :: Num a => [a] -> Double
mean [] = error "Trying to calculate mean of 0 values"
mean x = sumx / lengthx
where
sumx = fromIntegral (sum x)
lengthx = fromIntegral length x
GHCI rejects the fromIntegral function because it expects an Integral type not a Num.
Is there a way to convert a Num, whatever its specific type, to a Double?
The problem with converting Num a => a to a Double is that a Num may not actually be a number at all. There is no requirement for a member of the Num class to be a number of some sort. You can go and implement an instance of Num for anything, even for unit.
One obvious real-life example is Complex: it has an instance of Num, but a complex number can't always be converted to a real one.
If you want your function to work with integers, just specify Integral as your constraint.
OK, I finally found the way to do this:
mean :: Fractional a => [a] -> a
mean xs = sum xs / fromIntegral (length xs)
This works even if I apply it to a list of Integers. I am not sure why because Fractional does not apply to Integers according to the documentation I have read.
My understanding of Haskell is still obviously quite limited.
A more general way to write it is to use Real:
mean :: (Real a, Fractional b) => [a] -> b
mean xs = realToFrac (sum xs) / fromIntegral (length xs)
But that is not completely satisfactory because this doesn't work on lists of Complex numbers or other non-Real numbers.

why is this snippet valid with an explicit value, but invalid as a function?

I'm trying to work a problem where I need to calculate the "small" divisors of an integer. I'm just bruteforcing through all numbers up to the square root of the given number, so to get the divisors of 10 I'd write:
[k|k<-[1...floor(sqrt 10)],rem 10 k<1]
This seems to work well. But as soon as I plug this in a function
f n=[k|k<-[1...floor(sqrt n)],rem n k<1]
And actually call this function, I do get an error
f 10
No instance for (Floating t0) arising from a use of `it'
The type variable `t0' is ambiguous
Note: there are several potential instances:
instance Floating Double -- Defined in `GHC.Float'
instance Floating Float -- Defined in `GHC.Float'
In the first argument of `print', namely `it'
In a stmt of an interactive GHCi command: print it
As far as I undrestand the actual print function that prints the result to the console is causing trouble, but I cannot find out what is wrong. It says the type is ambiguous, but the function can clearly only return a list of integers. Then again I checked the type, and it the (inferred) type of f is
f :: (Floating t, Integral t, RealFrac t) => t -> [t]
I can understand that fshould be able to accept any real numerical value, but can anyone explain why the return type should be anything else than Integral or int?
[k|k<-[1...floor(sqrt 10)],rem 10 k<1]
this works because the first 10 is not the same as the latter one - to see this, we need the type signature of your functions:
sqrt :: Floating a => a -> a
rem :: Integral a => a -> a -> a
so the first one means that it works for stuff that have a floating point representation - a.k.a. Float, Double ..., and the second one works for Int, Integer (bigint), Word8 (unsigned 8bit integers)...
so for the 10 in sqrt 10 the compiler says - ahh this is a floating point number, null problemo, and for the 10 in rem 10 k, ahh this is an integer like number, null problemo as well.
But when you bundle them up in a function - you are saying n has to be a floating point and an integral number, the compiler knows no such thing and - complains.
So what do we do to fix that (and a side note ranges in haskell are indicated by .. not ...!). So let us start by taking a concrete solution and generalize it.
f :: Int -> [Int]
f n = [k|k <- [1..n'],rem n k < 1]
where n' = floor $ sqrt $ fromIntegral n
the neccessary part was converting the Int to a floating point number. But if you are putting that in a library all your users need to stick with using Int which is okay, but far from ideal - so how do we generalize (as promised)? We use GHCi to do that for us, using a lazy language we ourselves tend to be lazy as well.
We start by commenting out the type-signature
-- f :: Int -> [Int]
f n = [k|k <- [1..n'],rem n k < 1]
where n' = floor $ sqrt $ fromIntegral n
$> ghci MyLib.hs
....
MyLib > :type f
f :: Integral a => a -> [a]
then we can take this and put it into the library and if someone worked with Word8 or Integer that would work as well.
Another solution would be to use rem (floor n) k < 1 and have
f :: Floating a, Integral b => a -> [b]
as the type, but that would be kind of awkward.

No instance for (Integral [t0]) error in Haskell code

I'm getting an error:
No instance for (Integral [t0]) when I run this haskell code.
boomBangs xs = [(a,b,c) |a<-[1..xs],b<-[1..xs],c<-[1..xs], xs <- xs `div` 2]
Where am I going wrong?
The problem is that you're trying to divide a list. In particular, xs `div` 2 is the incorrect expression.
You can get this from the error message: it's complaining that [t0] does not behave like an integer (e.g. it isn't in the Integral class). [t0] is just a list of stuff--the t0, being in lowercase, is a type variable that represntes any type.
Since lists of stuff aren't numbers, we can't really know how to divide them.
You can see why you get this exact error message by looking at the type of div:
div :: Integral i => i -> i -> i
All this means is that given some type i in the Integral class, you can divide two of them together to get a third. Since lists of things are not part of the integral class, you can't divide them and so you get an error.
If div had a concrete type like div :: Int -> Int -> Int, you would get an error telling you that it can't match the expected type Int with the actual type [t0]. However, since the type actually contains a variable i, the error is a bit more complex: [t0] cannot be a valid type to use in place of i because it is not in the Integral class.
What you said was:
Give me a tuple of a, b, and c:
[ (a, b, c)
For each a, b, and c in the list of values from 1 to xs1:
| a <- [1..xs1]
, b <- [1..xs1]
, c <- [1..xs1]
For each xs2 in the quotient of xs1 and 2.
, xs2 <- xs1 `div` 2
]
If you compile with warnings enabled (-Wall) or turn them on in GHCi (:set -Wall) then you’ll get a warning that the xs in xs <- ... shadows the xs in boomBangs xs = ..., and also that it’s unused. Obviously this kind of warning can be very helpful, as it points right to your problem.
Since xs1 is the input to your function, you end up with a type like this:
(Integral [t]) => [t] -> [([t], [t], [t])]
Which is to say that the function takes a list (xs1) that can act as a number ((`div` 2)) and gives you back a list of tuples of such lists. Even though you’re trying to divide a list by a number, GHC allows it and infers a more general type because you could have defined an Integral instance for lists. It only discovers that you haven’t when you actually try to use the function on a concrete type. Writing down type signatures can help keep the compiler grounded and give you better error messages.
I can only guess you meant for boomBangs to have a type like:
Integral t => [t] -> [(t, t, t)]
Or just:
[Int] -> [(Int, Int, Int)]
In which case maybe you were thinking of something like this:
[ (a, b, c)
| x <- xs
, a <- [1..x `div` 2]
, b <- [1..x `div` 2]
, c <- [1..x `div` 2]
]

I don't understand number conversions in Haskell

Here is what I'm trying to do:
isPrime :: Int -> Bool
isPrime x = all (\y -> x `mod` y /= 0) [3, 5..floor(sqrt x)]
(I know I'm not checking for division by two--please ignore that.)
Here's what I get:
No instance for (Floating Int)
arising from a use of `sqrt'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `floor', namely `(sqrt x)'
In the expression: floor (sqrt x)
In the second argument of `all', namely `[3, 5 .. floor (sqrt x)]'
I've spent literally hours trying everything I can think of to make this list using some variant of sqrt, including nonsense like
intSqrt :: Int -> Int
intSqrt x = floor (sqrt (x + 0.0))
It seems that (sqrt 500) works fine but (sqrt x) insists on x being a Floating (why?), and there is no function I can find to convert an Int to a real (why?).
I don't want a method to test primality, I want to understand how to fix this. Why is this so hard?
Unlike most other languages, Haskell distinguishes strictly between integral and floating-point types, and will not convert one to the other implicitly. See here for how to do the conversion explicitly. There's even a sqrt example :-)
The underlying reason for this is that the combination of implicit conversions and Haskel's (rather complex but very cool) class system would make type reconstruction very difficult -- probably it would stretch it beyond the point where it can be done by machines at all. The language designers felt that getting type classes for arithmetic was worth the cost of having to specify conversions explicitly.
Your issue is that, although you've tried to fix it in a variety of ways, you haven't tried to do something x, which is exactly where your problem lies. Let's look at the type of sqrt:
Prelude> :t sqrt
sqrt :: (Floating a) => a -> a
On the other hand, x is an Int, and if we ask GHCi for information about Floating, it tells us:
Prelude> :info Floating
class (Fractional a) => Floating a where
pi :: a
<...snip...>
acosh :: a -> a
-- Defined in GHC.Float
instance Floating Float -- Defined in GHC.Float
instance Floating Double -- Defined in GHC.Float
So the only types which are Floating are Floats and Doubles. We need a way to convert an Int to a Double, much as floor :: (RealFrac a, Integral b) => a -> b goes the other direction. Whenever you have a type question like this, you can ask Hoogle, a Haskell search engine which searches types. Unfortunately, if you search for Int -> Double, you get lousy results. But what if we relax what we're looking for? If we search for Integer -> Double, we find that there's a function fromInteger :: Num a => Integer -> a, which is almost exactly what you want. And if we relax our type all the way to (Integral a, Num b) => a -> b, you find that there is a function fromIntegral :: (Integral a, Num b) => a -> b.
Thus, to compute the square root of an integer, use floor . sqrt $ fromIntegral x, or use
isqrt :: Integral i => i -> i
isqrt = floor . sqrt . fromIntegral
You were thinking about the problem in the right direction for the output of sqrt; it returned a floating-point number, but you wanted an integer. In Haskell, however, there's no notion of subtyping or implicit casts, so you need to alter the input to sqrt as well.
To address some of your other concerns:
intSqrt :: Int -> Int
intSqrt x = floor (sqrt (x + 0.0))
You call this "nonsense", so it's clear you don't expect it to work, but why doesn't it? Well, the problem is that (+) has type Num a => a -> a -> a—you can only add two things of the same type. This is generally good, since it means you can't add a complex number to a 5×5 real matrix; however, since 0.0 must be an instance of Fractional, you won't be able to add it to x :: Int.
It seems that (sqrt 500) works fine…
This works because the type of 500 isn't what you expect. Let's ask our trusty companion GHCi:
Prelude> :t 500
500 :: (Num t) => t
In fact, all integer literals have this type; they can be any sort of number, which works because the Num class contains the function fromInteger :: Integer -> a. So when you wrote sqrt 500, GHC realized that 500 needed to satisfy 500 :: (Num t, Floating t) => t (and it will implicitly pick Double for numeric types like that thank to the defaulting rules). Similarly, the 0.0 above has type Fractional t => t, thanks to Fractional's fromRational :: Rational -> a function.
… but (sqrt x) insists on x being a Floating …
See above, where we look at the type of sqrt.
… and there is no function I can find to convert an Int to a real ….
Well, you have one now: fromIntegral. I don't know why you couldn't find it; apparently Hoogle gives much worse results than I was expecting, thanks to the generic type of the function.
Why is this so hard?
I hope it isn't anymore, now that you have fromIntegral.

Resources