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.

有帮助吗?

解决方案

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.

其他提示

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 Orderable!

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.

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.

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top