module Naturales where data N = Z | S N deriving Show {-declarando el conjunto N como derivado de (Eq, Show) se le indica que son del tipo de las clase Eq y Show. Esto asegura que los objetos del tipo pueden ser comparados por igualdad y se pueden mostrar por pantalla-} instance Eq N where Z == Z = True S n == S m = n == m _ == _ = False natError = error "Los naturales no pueden ser negativos" {- Al derivar de Num se podrá usar "-" y es necesario para poder realizar sustracciones. Nos definimos una función " natError " que señala un error cuando se intenta producir a un natrural negativo-} instance Num N where Z + b = b S a + b = S (a + b) a - Z = a S a - S b = a - b _ - _ = natError a * Z = Z a * (S b) = a + a * b abs = id signum Z = Z signum _ = S Z fromInteger n | n == 0 = Z | n > 0 = S $ fromInteger (n-1) | otherwise = natError {-La declaración como instancia de Num asegura que esté en la clase Num. Aquí es donde se encuentran las funciones adición, multiplicación, signo, valor absoluto, así como una función de conversión de tipo fromInteger. Colocando las definiciones apropiadas se habilita el uso de los nombres estándar para estos operadores-} instance Integral N where toInteger Z = 0 toInteger (S n) = 1 + toInteger n a `quotRem` b | a < b = (Z, a) | otherwise = (S q, r) where (q, r) = (a-b) `quotRem` b div a = fst.quotRem a mod a =snd.quotRem a instance Real N where toRational = toRational.toInteger instance Enum N where toEnum = fromInteger.toInteger fromEnum = fromInteger.toInteger instance Ord N where (S a) <= (S b) = a <= b a <= _ = a == Z {-La declaración de N como instancia de Ord. El código para la clase Ord proporciona métodos para las relaciones <=, <,> =,>, y para los operadores de comparación máximo y mínimo, el poner N en esta clase nos provee de todos ellos-}