tags:

views:

210

answers:

4

Say i have a function prototype as follows:

func :: [Int] -> [Int]

How is it possible to enforce only a non-negative list of integers as input arguments? I would have to change the param type from [Int] to what.. ? At this fair moment it works with func [-1,-2], i only want it to work with [1,2] i.e. with the interpreter spewing the error message.

+4  A: 

Have you tried http://hackage.haskell.org/package/non-negative ?

KennyTM
I hoping that someone would show how to do this with types, but now I can see that this is impossible - from the comment for the NonNegative.C type class in non-negative: "Instances of this class must ensure non-negative values. We cannot enforce this by types, but the type class constraint NonNegative.C avoids accidental usage of types which allow for negative numbers." How disappointing :-)
liwp
+1  A: 

You could use Peano numbers, changing your function's type to [Peano] -> .... But then you will have to add conversion functions from integers to peano numbers and back whenever you call your function.

Or you could add a runtime check:

func xs
  | any (< 0) xs  = error "only non-negative integers allowed as input"
  | otherwise     = ...

Note that the latter solution makes your function strict.

Martijn
+4  A: 
newtype NonNegative a = NonNegative a

toNonNegative :: (Num a, Ord a) => a -> NonNegative a
toNonNegative x
  | x < 0 = error "Only non-negative values are allowed."
  | otherwise = NonNegative x

fromNonNegative :: NonNegative a -> a
fromNonNegative (NonNegative x) = x

Just be careful to never use the NonNegative constructor directly. This will be easier if you put this in a separate module and don't export it.

Also, now you can use (map toNonNegative) to lazily transform a list of numbers.

This will still require a runtime check wherever you inject raw numbers.

Alternatively, you can use Data.Word.

Dagititis
A: 

The wiki page on smart constructors may give you some idea.

Wei Hu