Reputation: 8023
I have the following functions:
which (x:xs) = worker x xs
worker x [] = x
worker x (y:ys)
| x > y = worker y ys
| otherwise = worker x ys
and am wondering how I should define the types signatures of these above functions which
and worker
?
For Example, which of the following ways would be best as a type signature for worker?
worker :: Num a => a -> [a] -> a
,
or
worker :: Ord a => a -> [a] -> a
?
I'm just really confused and don't get which these three I should choose. I'd appreciate your thoughts. Thanks.
Upvotes: 1
Views: 1491
Reputation: 53665
Ask ghci and see what it says. I just copy-pasted your code as is into a file and loaded it into ghci. Then I used :t
which is a special ghci command to determine the type of something.
ghci> :t which
which :: (Ord t) => [t] -> t
ghci> :t worker
worker :: (Ord a) => a -> [a] -> a
Haskell's type inference is pretty smart in most cases; learn to trust it. Other answers sufficiently cover why Ord
should be used in this case; I just wanted to make sure ghci was clearly mentioned as a technique for determining the type of something.
Upvotes: 2
Reputation: 10268
Edit: Altered my answer after comments.
It depends on what you want to being able to compare. If you want to being able to compare Double
, Float
, Int
, Integer
and Char
then use Ord
. If you only want to being able to compare Int
then just use Int
.
If you have another problem like this, just look at the instances of the type class to tell which types you want to be able to use in the function.
Upvotes: 0
Reputation: 377
If you think about what your functions do, you'll see that which xs
returns the minimum value in xs
. What can have a minimum value? A list of something Ord
erable!
Upvotes: 3
Reputation: 177574
If you define the function without an explicit type signature, Haskell will infer the most general one. If you’re unsure, this is the easiest way to figure out how your definition will be read; you can then copy it into your source code. A common mistake is incorrectly typing a function and then getting a confusing type error somewhere else.
Anyway, you can get info on the Num
class by typing :i Num
into ghci, or by reading the documentation. The Num
class gives you +
, *
, -
, negate
, abs
, signum
, fromInteger
, as well as every function of Eq
and Show
. Notice that <
and >
aren’t there! Requiring values of Num
and attempting to compare them will in fact produce a type error — not every kind of number can be compared.
So it should be Ord a => ...
, as Num a => ...
would produce a type error if you tried it.
Upvotes: 6
Reputation: 203
I would always go with the Ord type constraint. It is the most general, so it can be reused more often.
There is no advantage to using Num over Ord.
Int may have a small advantage as it is not polymorphic and would not require a dictionary lookup. I would stil use Ord and use the specialize pragma if I needed to for performance.
Upvotes: 0