Fedo
Fedo

Reputation: 349

Wrong function type declaration

I have the following function that sholud return only odd numbers from the List

oddsOnly :: Integral a => [a] -> [a]
oddsOnly [] = []
oddsOnly (x:xs)
 |odd x = x : oddsOnly xs
 |otherwise = oddsOnly xs

My question is about the aim of using

Integral a =>

Actually it is not posssible to implement such function with such type declaration

oddsOnly :: [a] -> [a]

As far as I know even and odd functions are in standart Prelude library so why simplified daclaration does not work?

Thanks in advance

Upvotes: 8

Views: 72

Answers (3)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476719

The signature of odd and even is odd :: Integral a => a -> Bool and even :: Integral a => a -> Bool respectively. So these contain an Integral a type constraint [Haskell-wiki].

A type constraint has nothing to do from where it is defined. It specifies that the function only is defined for a subset of types. Only for types that are members of the Integral typeclass, you can use the function. Integral types are types like that specify a subset of ℤ, so Int, Int64, Word8, Integer, … Types. odd and even do not make much sense over Floats, Strings, Chars, etc. What would that mean?

By thus specifying the Integral a => type constraint, you specify that this function can only work with integer-like items.

Note that you can use filter :: (a -> Bool) -> [a] -> [a] here to retain only odd numbers:

oddsOnly :: Integral a => [a] -> [a]
oddsOnly = filter odd

Upvotes: 8

bradrn
bradrn

Reputation: 8467

Let’s look at the type signature of odd: odd :: Integral a => a -> Bool. So to use odd with a parameter, that parameter needs to be Integral. This makes sense intuitively: as @ForceBru said in another answer, you can’t tell whether e.g. a float such as 1.5 or a string such as "hello" is odd, as the notion of oddness is only defined for integral values.

Upvotes: 3

ForceBru
ForceBru

Reputation: 44858

why simplified daclaration does not work?

Because you can't tell if a string is odd or not. Or if a float is odd or not. In general, it's not possible to tell if a value of any type a is odd or not because the notion of being odd may not be defined for this type.

It is defined, however, for Integral types, so you must specify that a is Integral.

In terms of Haskell, odd works on Integrals only:

Prelude> :t odd
odd :: Integral a => a -> Bool

Thus, you must pass it a value of a type that is Integral.

Upvotes: 9

Related Questions