Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell: Difference between (Num a, Ord a) & (Integral a)

Tags:

haskell

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

like image 863
Karthikeyan Avatar asked Dec 10 '22 02:12

Karthikeyan


1 Answers

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 1s.

like image 177
Willem Van Onsem Avatar answered Dec 12 '22 14:12

Willem Van Onsem