Confusion with Haskell type inference - haskell

I don't understand why the following function works:
isLongerThanN :: Integral n => n -> [a] -> Bool
isLongerThanN n xs = length xs > fromIntegral n
but the following doesn't:
isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n
which throws the error
Could not deduce (n ~ Int)
from the context (Integral n)
bound by the type signature for
isLongerThanN' :: Integral n => n -> [a] -> Bool
at blah.hs:140:1-35
`n' is a rigid type variable bound by
the type signature for
isLongerThanN' :: Integral n => n -> [a] -> Bool
at blah.hs:140:1
In the second argument of `(>)', namely `n'
In the expression: length xs > n
In an equation for `isLongerThanN'':
isLongerThanN' n xs = length xs > n
(which I've likely misunderstood)
If anything, I would expect it to be the other way around, since fromIntegral is effectively broadening variable n's type.

Consider the expression that doesn't work
isLongerThanN' :: Integral n => n -> [a] -> Bool
isLongerThanN' n xs = length xs > n
n can be any integer-y type, so it can be passed an Integer or Word or Int. (>) has type Ord a => a -> a -> Bool so both its left and right operand have to be of the same type. length xs returns an Int so this type has to be that. But, n can be any Integral, not necessarily Int, so we need some way of allowing n to be converted to an Int. This is what fromIntegral does (the fact that it also allows n to be any Num is basically irrelevant).
We could expand the working version to look like:
toInt :: Integral n => n -> Int
toInt = fromIntegral
isLongerThanN :: Integral n => n -> [a] -> Bool
isLongerThanN n xs = length xs > toInt n
which makes it clearer that we're using a specialised version of fromIntegral.
(Note that isLongerThanN n xs = fromIntegral (length xs) > n also works, because it allows the result of length to match up with the type of n.)

Related

Haskell: Finding the type of an expression involving map

I am trying to find the type of the following Haskell expression:
map (\x -> x + 1)
Since the map function is partially applied, it will return another function.
In GHCI, the type of the function that is returned is:
let res = map (\x -> x + 1)
:t res
map (\x -> x + 1) :: Num b => [b] -> [b]
Would the type of the above expression be the type of the function that is returned? Any insights are appreciated.
Yes, that is the type of the function which is returned.
But how does GHC figure this out? Well, let's look at the type of just plain map:
map :: (a -> b) -> [a] -> [b]
And now let's look at the type of \x -> x + 1:
(\x -> x + 1) :: Num n => n -> n
(In case you don't know yet, this means that it converts n to n, where n can be any type which is an instance of Num i.e. n is any number type.)
So matching up the types, we get:
map :: (a -> b) -> [a] -> [b]
(\x -> x + 1) :: Num n => n -> n
So:
map (\x -> x + 1) :: Num n => [n] -> [n]
Which is the same as what GHCi reports.

Apply comparison between Integral and Fractional

I want to check if an Integral is a square:
isSquare :: Integral n => n -> Bool
isSquare n = (>1) $ length (filter (\x -> n / x == x) numList)
where numList = reverse [1..n]
Apart from whether or not iterating through a list is the right approach here, when I try to compile this function I get the error:
No instance for (Fractional Int) arising from a use of ‘/’
My understanding of this is that since I am binding n to the Integral type, by dividing it I am breaking the function's rigid type construction. How can I fix my function so that it compiles?
You could add fromIntegral to everything to get Fractionals:
filter (\x -> fromIntegral n / fromIntegral x == fromIntegral x) numList
Or just square the number instead:
filter (\x -> n == x ^ 2)
Also, your length check shouldn’t be >1. ==1 would make more sense, but you should use null to avoid having to try every number every time (besides using a faster algorithm in the first place).
isSquare :: Integral a => a -> Bool
isSquare n = not $ null $ filter (\x -> n == x ^ 2) numList
where numList = [n,n-1..1]

No instance for (Num a) arising from a use of `sum' - Instance Num

this function works fine:
fromDigits :: [Int] -> Int
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: [Int] -> Int -> [Int]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
But if i want to change the type signature from the function, it does not work:
fromDigits :: (Num a) => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: (Num a) => [a] -> a -> [a]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
Shouldn't this work too?
Almost, but not quite. The basic problem is that length has type [a]->Int. This will work:
fromDigits :: Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: Num b => [b] -> Int -> [b]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
As Oleg Grenrus points out, one should always be careful to check if Int might overflow. It is in fact possible for this to happen if Int is 30, 31, or 32 bits, although it is relatively unlikely. However, if that is a concern, there is a way around it, using another function:
lengthIsExactly :: Integral n => n -> [a] -> Bool
lengthIsExactly = -- I'll let you figure this one out.
-- Remember: you can't use `length` here,
-- and `genericLength` is horribly inefficient,
-- and there's a completely different way.
You can make it easier to see how the types of fromDigits and f match up using a GHC extension. Enable the extension by adding
{-# LANGUAGE ScopedTypeVariables #-}
to the very top of your source file. Then you can write
fromDigits :: forall a . Num a => [a] -> a
fromDigits n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: [a] -> Int -> [a]
f n x = if (x==length n) then []
else (10^x):f n (x+1)
This way, it's clear that the list arguments all have the same type.
The problem is that you are using other functions that require even more of type a than just Num a
(^) requires "Integral a"
This works
fromDigits' :: (Num a, Integral a)=>[a] -> a
fromDigits' n = sum (zipWith (\x y -> x*y) (n) (f n 0))
where
f :: (Num a, Integral a)=>[a] -> a -> [a]
f n x = if (x==fromIntegral (length n)) then []
else (10^x):f n (x+1)

Haskell error No instance for (Floating Int)

This code is to get the distance between 2 points but i got a problem!
UPDATED by #EduardoLeon
rango2 :: Int -> [Int] -> [[Int]] -> [Int]
rango2 a b list = if (verif [(list!!a!!0),(list!!a!!1),(list!!a!!2)] (b)) then [1]
else [0]
verif :: [Int] -> [Int] -> Bool
verif a b = if ((distance a b) > a!!2) then True
else False
difference :: Num a => [a] -> [a] -> [a]
difference xs ys = zipWith (-) xs ys
dotProduct :: Num a => [a] -> [a] -> a
dotProduct xs ys = sum $ zipWith (*) xs ys
distance :: Floating a => [a] -> [a] -> a
distance xs ys = sqrt $ dotProduct zs zs
where
zs = difference xs ys
EDITED: I cant change Int to Float, because im doing operations with lists and now
throw this error!
Proyecto.hs:71:18:
No instance for (Floating Int) arising from a use of `distance'
Possible fix: add an instance declaration for (Floating Int)
In the first argument of `(>)', namely `(distance a b)'
In the expression: ((distance a b) > a !! 2)
In the expression:
if ((distance a b) > a !! 2) then True else False
To answer your concrete question: Unlike more conventional languages, Haskell does not automatically cast integers to floats. In fact, the very notion of casting does not exist in Haskell. You need to use the function fromIntegral to convert integers to other numeric types. You could try the following in ghci:
> let x = 5 :: Integer
> sqrt x
<interactive>:3:1:
No instance for (Floating Integer) arising from a use of `sqrt'
In the expression: sqrt x
In an equation for `it': it = sqrt x
> let y = fromIntegral x :: Double
> sqrt y
2.23606797749979
I would also like to make some other suggestions regarding your coding style:
Decompose your functions into smaller functions that do exactly one thing and do it well.
The function (!!) traverses a linked list to find the n-th element. This is an O(n) operation, which is more expensive than necessary if you intend to retrieve multiple elements from the same list. Prefer solutions that avoid traversing the same list more than once.
Here is how I would find the distance between two points:
difference :: Num a => [a] -> [a] -> [a]
difference xs ys = zipWith (-) xs ys
dotProduct :: Num a => [a] -> [a] -> a
dotProduct xs ys = sum $ zipWith (*) xs ys
distance :: Floating a => [a] -> [a] -> a
distance xs ys = sqrt $ dotProduct zs zs
where
zs = difference xs ys
I was searching and i saw that i need to change Int to Float?
Just change the type signature to Float and things will start working:
verif :: [Float] -> [Float] -> Bool
You need to change the type signature of your code to indicate that it works with floating data since sqrt function operates on that. A more generic solution would be this:
verif :: (Floating a, Ord a) => [a] -> [a] -> Bool
verif a b = if (sqrt((((b!!0)-(a!!0))*((b!!0)-(a!!0)))+(((b!!1)-(a!!1))*((b!!1)-(a!!1)))) < a!!3)
then True
else if (sqrt((((b!!0)-(a!!0))*((b!!0)-(a!!0)))+(((b!!1)-(a!!1))*((b!!1)-(a!!1)))) == a!!3)
then True
else False
The use of the !! function isn't encouraged in Haskell. I would suggest you to rewrite the function in a more functional way.
I suggest that you revisit your design. What are the meanings of the lists a and b in verif? It looks like you are finding the distance between two points. You can create a type:
data Point = Point Double Double
and a function
distance :: Point -> Point -> Double
to make your code much more readable.
This should also eliminate doing the same calculation twice by using a where clause or let binding.

Couldn't match expected type [a] with actual type `Integer -> [Integer]'

I have the following code that finds the divisors of an Integer, then all the subsets of the divisors, then sums all the divisors in each subset, then tests to see if that Integer is represented in the list of summations. In findWeird this is performed over a list of Integers.
allSubsets :: (Integral a ) => [a] -> [[a]]
allSubsets [] = [[]]
allSubsets ( n : nr ) = allSubsets nr ++ map (n:) (allSubsets nr)
sumAllSubsets :: (Integral a ) => [a] -> [a]
sumAllSubsets s = map sum (allSubsets s)
allDivisors :: (Integral a) => a -> [a]
allDivisors 0 = []
allDivisors n | n > 0 = [d | d <- [1..n], n `mod` d == 0]
| n < 0 = -1 : allDivisors (-n)
findWeird :: (Integral a) => [a] -> [a]
findWeird [] = []
findWeird (n:nn) = ( if n `elem` (AS.sumAllSubsets (DFL.allDivisors))
then []
else [n]) ++ findWeird nn
Problem is that I get the error:
test.hs:15:61:
Couldn't match expected type `[a]'
with actual type `Integer -> [Integer]'
In the first argument of `sumAllSubsets', namely `(allDivisors)'
In the second argument of `elem', namely
`(sumAllSubsets (allDivisors))'
In the expression: n `elem` (sumAllSubsets (allDivisors))
But as far as know allDivisors produces a [Integral] and sumAllSubsets takes an [Integral], so I was just wondering if anyone could help. Thanks.
I think the problem is you're not actually apply allDivisors to anything:
AS.sumAllSubsets (DFL.allDivisors)
is just applying sumAllSubsets to the function allDivisors, not to its [Integer] return value. Maybe you meant AS.sumAllSubsets (DFL.allDivisors n), that is, applying allDivisors to n?
(BTW, findWeird is just doing a filter, and can be written as
findWeird nn = filter (\n -> n `notElem` (sumAllSubsets $ allDivisors n)) nn
where I've also taken the liberty to reduce some nesting via the ($) operator.)

Resources