Haskell: Finding the type of an expression involving map - haskell

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.

Related

What would the type of the following be?

Im just starting learn Haskell new, I'm struggling with determining the type for the following:
1) one x = [x]
2) three x = (x,x,x)
3) first x y = x
4) mult m n = m*n
5) [(False,’0’),(True,’1’)]
one x = [x] is a that takes an element and returns a list with that element only, so it has type one :: a -> [a]
three x = (x,x,x) has trivial type three :: a -> (a,a,a)
first x y = x looks like the Prelude function const that has type first :: a -> b -> a
mult m n = m*n has the same type as (*), which is (*) :: Num a => a -> a -> a
[(False,’0’),(True,’1’)] is not even a function, so has simple type :: [(Bool, Char)]
Remember you can always use they GHCi function :t to return the type of an expression

How would you declare the types of these functions in Haskell?

So I'm learning about Haskell at the moment, and I came across this question:
The type of a function f is supposed to be a->[a]->a. The
following definitions of f are incorrect because their types are all
different from a->[a]->a:
i. f x xs = xs
ii. f x xs = x+1
iii. f x xs = x ++ xs
iv. f x (y:ys) = y
My answers as I see it are:
i) f :: a -> a -> a
This is because x or xs can be of any value and is not a list as it does not contain the ':' operator.
ii) f :: Int -> a -> Int
This is because the + operator is used on x, meaning x is of type Int.
iii) f :: Eq a => a -> a -> a
The ++ operators are used, therefore in order to concatenate they must be of the same type..?
iv) f :: a -> [a] -> a
f returns an element from the list.
The last one is definitely wrong, because it can't be of type a -> [a] -> a. Are there any others I did wrong, and why? I'm hoping I can fully understand types and how to find out the types of functions.
i) f :: a -> a -> a
f x xs = xs
This is because x or xs can be of any value and is not a list as it does not contain the ':' operator.
True, but it also does not have to be of the same type!
So, it's actually f :: a -> b -> b.
ii) f :: Int -> a -> Int
f x xs = x+1
This is because the + operator is used on x, meaning x is of type Int.
Correct. (Actually, in Haskell we get Num b => b -> a -> b which generalized the Int to any numeric type, but it's not that important.)
iii) f :: Eq a => a -> a -> a
f x xs = x ++ xs
The ++ operators are used, therefore in order to concatenate they must be of the same type..?
True, but they must be lists. Also, Eq is only needed if you use == or something which compares values.
Here, f :: [a] -> [a] -> [a].
iv) f :: a -> [a] -> a
f x (y:ys) = y
f returns an element from the list.
The type of x does not have to be the same. We get f :: b -> [a] -> a.
i. f x xs = xs
(...)
i) f :: a -> a -> a
Although this can be a type signature, you make it too restrictive. The function takes two parameters x and xs. Initially we can reason that x and xs can have different types, so we say that x :: a, and xs :: b. Since the function returns xs, the return type is b as well, so the type is:
f :: a -> b -> b
f x xs = xs
ii. f x xs = x+1
(...)
ii) f :: Int -> a -> Int
Again you make the function too restrictive. Let us again assume that x :: a and xs :: b have different types. We see that we return x + 1 (or in more canonical form (+) x 1. Since (+) has signature (+) :: Num c => c -> c -> c (we here use c since a is already used), and 1 has signature 1 :: Num d => d, we thus see that we call (+) with x and 1, as a result we know that a ~ c (a and c are the same type), and c ~ d, so as a result we obtain the signature:
f :: Num c => c -> b -> c
f x xs = x+1
iii. f x xs = x ++ xs
(...)
iii) f :: Eq a => a -> a -> a
This is wrong: we here see that f has two parameters, x :: a and xs :: b. We see that we return (++) x xs. Since (++) has signature (++) :: [c] -> [c] -> [c], we thus know that a ~ [c] and b ~ [c], so the type is:
f :: [c] -> [c] -> [c]
f x xs = x ++ xs
iv. f x (y:ys) = y
(...)
iv) f :: a -> [a] -> a
This is again too restrictive. Here we see again two parameters: x and (y:ys). We first generate a type a for x :: a, and (y:ys) :: b, since the pattern of the second parameter is (y:ys), this is a list constructor with as parameters (:) :: c -> [c] -> [c]. As a result we can derive that y :: c, and ys :: [c], furthermore the pattern (y:ys) has type [c]. Since the function returns y, we know that the return type is c, so:
f :: a -> [c] -> c
f x (y:ys) = y
Note: you can let Haskell derive the type of the function itself. In GHCi you can use the :t command to query the type of an expression. For example:
Prelude> f x (y:ys) = y
Prelude> :t f
f :: t1 -> [t] -> t

Occurs check: cannot construct the infinte type

I'm trying to construct a list of all prime numbers using the sieve method:
primes remNum =
let i = head remNum
in i : primes (filter (\(x) -> x mod i /= 0) (tail remNum))
The error that I'm getting is:
* Occurs check: cannot construct the infinite type:
t ~ (a -> a -> a) -> t -> a1
Expected type: [t]
Actual type: [(a -> a -> a) -> t -> a1]
* In the first argument of `head', namely `remNum'
In the expression: head remNum
In an equation for `i': i = head remNum
* Relevant bindings include
i :: t (bound at lib.hs:30:7)
remNum :: [(a -> a -> a) -> t -> a1] (bound at lib.hs:29:8)
primes :: [(a -> a -> a) -> t -> a1] -> [t] (bound at lib.hs:29:1)
I don't understand why remNum is bound to [(a-> a -> a) -> t -> a1] while i is bound to t, since surely head :: [a] -> a would imply remNum::[t]?
So the idea with this is that it is supplied a lazy list of all numbers and then essentially maintains a list of removed values.
It would be called:
numsFrom n = n : numsFrom (n + 1)
primes numsFrom 2
x mod i
is not what you intended. You want to use
x `mod` i
The problem with the first is that since both i and x are from the list, they must have the same type. Let's call that type X. What is X? Well, since we use x mod, it should start with mod's type:
type X = (Integer -> Integer -> Integer) -> …
Since the other "parameter" is i, which has the same type as x, we end up with:
type X = (Integer -> Integer -> Integer) -> X -> …
which is an infinite type.
So the proper solution would be
primes remNum =
let i = head remNum
in i : primes (filter (\(x) -> x `mod` i /= 0) (tail remNum))
or
primes remNum =
let i = head remNum
in i : primes (filter (\(x) -> mod x i /= 0) (tail remNum))
or (with pattern matching)
primes (i:remNums) = x : primes (filter (\x -> mod x i /= 0) remNums)

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)

Confusion with Haskell type inference

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.)

Resources