2009-10-07 12 views
14

Tengo una pregunta bastante general sobre el sistema de tipos de Haskell. Estoy tratando de familiarizarse con él, y tengo la siguiente función:Tipo específico de devolución dentro de Haskell

getN :: Num a => a 
getN = 5.0 :: Double 

Cuando intento compilar esto, me sale el siguiente error:

Couldn't match expected type `a' against inferred type `Double' 
    `a' is a rigid type variable bound by 
     the type signature for `getN' at Perlin.hs:15:12 
In the expression: 5.0 :: Double 
In the definition of `getN': getN = 5.0 :: Double 

Según tengo entendido esto, el la función está configurada para "devolver" un tipo en la clase Num. El doble está en esta clase (http://www.zvon.org/other/haskell/Outputprelude/Num_c.html), así que habría esperado que estaría bien "devolver" un Doble en este caso.

¿Alguien puede explicar esto por favor?

Respuesta

15

se espera Una función con la firma Num a => a a trabajar para cualquier tipo en la clase Num. La implementación 5.0 :: Double solo funciona para tipo, no para todos los tipos de la clase, por lo que el compilador se queja.

Un ejemplo de una función genérica sería:

square :: (Num a) => a -> a 
square x = x * x 

Esto funciona para cualquier tipo que es un Num. Funciona para dobles, enteros y cualquier otro número que desee usar. Por eso puede tener una firma de tipo genérico que solo requiera que el parámetro esté en la clase Num. (Tipo de clase Num es necesario porque la función usa la multiplicación con *, que se define allí)

+0

+1 - Podemos escribir el tipo de función anterior como 'forall a. Num a => a' -> Tiene que funcionar * para cualquier tipo *. – Dario

8

Para agregar a la respuesta de este: Haskell no está orientado a objetos. No es cierto que Double es una subclase de Num, por lo que no puede devolver Double si promete devolver un valor Num polimórfico, como puede hacerlo, por ejemplo, en Java.

Cuando escribe getN :: Num a => a, promete devolver un valor que es completamente polimórfico dentro de la restricción Num. Efectivamente, esto significa que solo puede usar funciones de la clase de tipo Num, como +, *, - y fromInteger.

3

Echa un vistazo tipos cuantificados existencialmente.

Una forma de resolverlo sería definir un nuevo tipo de datos

data NumBox = forall n. Num n => NumBox n 

Tendrá -XExistentialQuantification a conseguir que esto funcione.

Ahora usted puede escribir algo como

getN :: NumBox 
getN = NumBox (5.0 :: Double) 

También puede definir una -lista NumBox como

let n3 = [NumBox (4.0 :: Double), NumBox (1 :: Integer), NumBox (1 :: Int) ] 
Cuestiones relacionadas