2

As a training exercise, I have written a polymorphic function to determine whether a given number is prime to either a single number or all of a list of numbers:

{-# LANGUAGE FlexibleInstances #-}
class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo (Integer) where
    ispt n d = 0 /= (rem n d)
instance PrimeTo ([Integer]) where
    ispt n [] = True
    ispt n (x:xs) = (ispt n x) && (ispt n xs)

To get this to work, I had to use FlexibleInstances, and I'm happy with that, but curious.

Under strict Haskell 98, as I understand it, I would need to add a type descriptor, T, to the instance definitions:

class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo (T Integer) where
    ispt n d = 0 /= (rem n d)
instance PrimeTo (T [Integer]) where
    ispt n [] = True
    ispt n (x:xs) = (ispt n x) && (ispt n xs)

but I haven't a clue what goes in place of "T", and I don't even know whether this is possible under Haskell 98.

So:

  1. Is this even possible under Haskell 98?
  2. If so, what would be used for T?
Brent.Longborough
  • 9,567
  • 10
  • 42
  • 62

1 Answers1

4

T can be Integer or [], as folllows:

class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo Integer where
    ispt n d = 0 /= (rem n d)
instance PrimeToList a => PrimeTo [a] where
    ispt = isptList  -- see below

Since the last one can only be about [a], we need a helper class PrimeToList. Here's the additional helper class and instance:

class PrimeToList a where
    isptList :: Integer -> [a] -> Bool

instance PrimeToList Integer where
    isptList n []     = True
    isptList n (x:xs) = ispt n x && isptList n xs

By the way, I'd rewrite the last definition using all:

    isptList n = all (ispt n)

The above shows the general technique. In your specific case, you can probably avoid the helper class and use

class PrimeTo a where
    ispt :: Integer -> a -> Bool
instance PrimeTo Integer where
    ispt n d = 0 /= (rem n d)
instance PrimeTo a => PrimeTo [a] where
    ispt n = all (ispt n)

This will also define PrimeTo [[Integer]], PrimeTo [[[Integer]]] and so on, so it is not a perfect replacement like the previous one.

chi
  • 111,837
  • 3
  • 133
  • 218