2010-01-15 18 views
8

decir que tengo un prototipo de la función de la siguiente manera:enteros no negativos

func :: [Int] -> [Int] 

¿Cómo es posible hacer cumplir solamente una lista no negativo de enteros como argumentos de entrada? Tendría que cambiar el tipo de parámetro de [Int] a qué ...? En este momento justo funciona con func [-1, -2], solo quiero que funcione con [1,2], es decir, con el intérprete arrojando el mensaje de error.

Respuesta

4
+0

que la esperanza de que alguien podría mostrar cómo hacer esto con los tipos, pero ahora puedo ver que esto es imposible - a partir de la observación de la clase de tipo NonNegative.C en no negativo: "Las instancias de esta clase deben garantizar valores no negativos. No podemos aplicar esto por tipos, pero la restricción de clase de tipo NonNegative.C evita el uso accidental de tipos que permiten números negativos". Que decepcionante :-) – liwp

1

Puede usar Peano numbers, cambiando el tipo de su función a [Peano] -> .... Pero luego deberá agregar funciones de conversión de números enteros a números peano y viceversa cada vez que llame a su función.

O usted podría agregar un control de tiempo de ejecución:

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

Tenga en cuenta que esta última solución hace que su función strict.

7
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 

Solo tenga cuidado de nunca utilizar el constructor NonNegative directamente. Esto será más fácil si coloca esto en un módulo separado y no lo exporta.

Además, ahora puede usar (map toNonNegative) para transformar perezosamente una lista de números.

Esto todavía requerirá un control en tiempo de ejecución dondequiera que inyecte números brutos.

Alternativamente, puede usar Data.Word.

0

En el paquete base de la versión> = 4.8.0.0, que se incluye en GHC 7.10.1 y por encima, ahora hay un tipo Natural el que hace lo que quiere - usted puede cambiar el código para:

import Numeric.Natural (Natural) 

func :: [Natural] -> [Int] 

es, sin embargo, más cerca de Integer que a Int, porque al igual que Integer ya diferencia de Int, no tiene valor máximo.

Debido Natural, como Integer, es una instancia de Num y Integral, todas las mismas operaciones aritméticas y las funciones de conversión están disponibles como se obtiene con Integer. Los intentos de calcular un Natural negativo lanzarán un Underflow en tiempo de ejecución, que es un ArithException. Además, convenientemente, puede crear un Natural utilizando sólo un literal entero, sin una conversión:

GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help 
Prelude> :m +Numeric.Natural 
Prelude Numeric.Natural> 2 :: Natural 
2 

Sin embargo, si usted prefiere permanecer en el dominio de los números enteros de tamaño fijo, no es una solución para eso, también - y ha estado por mucho más tiempo - Word desde the module Data.Word (que también contiene, por ejemplo, Word8 para enteros no negativos de 8 bits). Utilizaría Word de la misma manera que Natural.Sin embargo, se advirtió - los Word tipos van en silencio desbordamiento, sin lanzar una excepción:

GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help 
Prelude> :m +Data.Word 
Prelude Data.Word> 2 :: Word 
2 
Prelude Data.Word> it - 4 
18446744073709551614 
Cuestiones relacionadas