Reputation: 41
Both the following declarations work for replicate' 3 5
. I am not able to understand why you need Num and Ord when Integral would do. The second one was what I came up with and the first one was here - http://learnyouahaskell.com/recursion.
What do I lost with just Integral?
1
replicate' :: (Num a, Ord a) => a -> b -> [b]
replicate' 0 x = []
replicate' n x = x:replicate' (n-1) x
2
replicate' :: (Integral a) => a -> b -> [b]
replicate' 0 x = []
replicate' n x = x:replicate' (n-1) x
Note: I need to give some clarification here after willem's answer below (he understood the question without this clarification). The code in http://learnyouahaskell.com/recursion is
replicate' :: (Num i, Ord i) => i -> a -> [a]
replicate' n x
| n <= 0 = []
| otherwise = x:replicate' (n-1) x
Not what I have mentioned in 1. Willem's reply explains all three snippets.
Also, a related question is available at Haskell type definition, => etc
Upvotes: 4
Views: 610
Reputation: 477513
Haskell always aims to construct the most generic type signature. If we take a look at the implementation:
replicate' :: (Num i, Ord i) => i -> a -> [a]
replicate' n x
| n <= 0 = []
| otherwise = x:replicate' (n-1) x
We see that the (<=) :: Ord a => a -> a -> Bool
function is applied to n
, and we calculate n-1
in the recursion (with (-) :: Num a => a -> a -> a
). The most generic type signature thus will add a Num
and Ord
type constraint on that number.
We thus can call replicate' 3.1415 1
, and it will return the first four items. But it is probably nonsensical to do that.
The Integral
typeclass is a typeclass for integral numbers. It supports integer division. Any Integral
type must be a member of the Real
and Enum
typeclass.
A type that is a member of the Real
typeclass, should support a function toRational :: Real a => a -> Rational
to convert that number to a Rational
, and furthermore should be a member of the Num
and Ord
typeclasses.
This thus means that if a type is a member of the Integral
typeclass, it is a member of Num
, Enum
, Ord
and Real
as well. You thus made the type more restrictive. But I think in the context of a replicate'
it makes perfect sense to do that.
Note that it might not be ideal to write:
replicate' :: (Num a, Ord a) => a -> b -> [b]
replicate' 0 x = []
replicate' n x = x:replicate' (n-1) x
In case we here call replicate (-3) 1
, or replicate 3.14 1
(as @leftroundabout pointed out), we will obtain an infinite list of 1
s.
Upvotes: 13