1

I'm trying to learn haskell from a book with exercises. I can't get through this one and I don't know what's the problem. So I to declare a << definition. In the case of 'a' has less divisors than proper divisors 'b' have, it should be true. Like 6 << 10, 6 have 4 divisors and 10 has 2 proper divisor so it should be False. I have made a definition for divisors and proper divisors, but when I'm trying to use them it just won't happen.

    divisors :: Integer -> [Integer]
    divisors a = [n | n <- [1..a], a `mod` n == 0]

    properDivisors :: Integer -> [Integer]
    properDivisors a = [n | n <- [2..a `div` 2], a `mod` n == 0]

    (<<) :: Num a => a -> a -> Bool
    x << y = divisors x < properDivisors y

The (<<) :: Num a => a -> a -> Bool is fixed.

2
  • Are you getting an error message or something? Commented Mar 3, 2015 at 22:03
  • Can you try to give this question a title that will indicate what the operator is actually supposed to do? Commented Mar 4, 2015 at 3:20

1 Answer 1

3

Your << operator would instead need the type Integral a => a -> a -> Bool, since both div and mod requires Integral, not just Num. If you can't use the Integral constraint then you'll have to write your own versions of div and mod that work with all Nums.

This can be seen if you comment out all your type signatures:

> :set +m
> let divisors a = [n | n <- [1..a], a `mod` n == 0]
|     properDivisors a = [n | n <- [2..a `div` 2], a `mod` n == 0]
|     x << y = divisors x < properDivisors y
divisors :: Integral t => t -> [t]
properDivisors :: Integral t => t -> [t]
(<<) :: Integral t => t -> t -> Bool

If we inspect the types of the functions used inside divisors and properDivisors we get

> :t mod
mod :: Integral a => a -> a -> a
> :t div
div :: Integral a => a -> a -> a
> :t (==)
(==) :: Eq a => a -> a -> Bool
> :i Integral
class (Real a, Enum a) => Integral a where
    ...
> :i Real
class (Num a, Ord a) => Real a where
    ...
> :i Ord
class Eq a => Ord a where
    ...

(the other constraints have no preconditions) so in order to use mod and div the type has to be Num, Eq, Ord, Enum, Real, and Integral, as this is the typeclass hierarchy set up in Haskell. The two built-in types that fit these constraints are Int and Integer. Since Float and Double do not implement Integral, but they do implement Num, there's no way you can use mod or div with just the Num constraint.

Sign up to request clarification or add additional context in comments.

4 Comments

Yes, I get that, the problem is that the task is to write the << operator as (<<) :: Num a => a -> a -> Bool. The divisors and properDivisors are my creations trying to solve the task. It seemed the easiest way of solving this but might be wrong.
Like I said, you can't use the built-in div and mod for this if you expect to only have the Num constraint. You'll have to write your own div and mod for this purpose. It'll be tough to do, since Num does not require Ord, and my first thought for implementing them would be to use subtraction and comparisons to approximate these functions, or to use signum/abs tricks since that would probably require at least Eq.
Also be warned that divisors x < properDivisors y is probably not what you're wanting, but rather length (divisors x) < length (properDivisors y). Using < with lists will just do an element-wise comparison until one list runs out of elements.
I cannot see how making it work with just Num is possible at all - Num has no methods for doing anything other than constructing new numbers. Maybe if the book is so old that it assumes Num is still a subclass of Eq and Show, you could do it in such a way that it works if the type is actually Integer, but it would still be meaningless for many Nums.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.