2011-11-30 7 views
5

Para las siguientes definiciones de las funciones triviales:¿Cuál es la diferencia entre estas dos definiciones de tipo de función?

printLength1::(Num a)=>String->a 
printLength1 s = length s 


printLength2::String->Int 
printLength2 s = length s 

Por qué no son lo mismo? ¿En qué situaciones debo elegir una sobre la otra?

y me sale este error para printLength1:

Couldn't match type `a' with `Int' 
     `a' is a rigid type variable bound by 
      the type signature for rpnc :: String -> a at test.hs:20:1 
    In the return type of a call of `length' 
    In the expression: length s 
    In an equation for `rpnc': rpnc s = length s 

entiendo este error. ¿Pero cómo puedo solucionar esto? Ya he leído algunas publicaciones aquí sobre la variable de tipo rígida, pero todavía no podía entender cómo solucionarlo.

Respuesta

9

La primera firma de tipo es más general. Significa que el resultado puede ser cualquier Num --es polimórfico en su tipo de devolución. Por lo tanto, el resultado de su primera función podría usarse como Int o Integer o cualquier otra instancia de Num.

El problema es que length devuelve un Int en lugar de cualquier instancia de Num. Puedes solucionar este problema utilizando fromIntegral:

printLength1 :: Num a => String -> a 
printLength1 s = fromIntegral $ length s 

Tenga en cuenta que la firma de fromIntegral . length (que es la versión libre de punto del código anterior) es Num c => [a] -> c. Esto coincide con la firma que especificó para su función printLength1.

+0

Gracias chicos. Espero que no haya más caprichos ocultos en el lenguaje. – osager

+3

@osager Esto no es un capricho, esta es una parte muy importante del sistema de tipos. Los tipos polimórficos (al menos los tipos polimórficos de rango 1) se convierten en tipos concretos según cómo se usan. Si escribe una firma de tipo que afirme que un tipo es polimórfico, debe ser realmente * be * polimórfico. – Carl

+1

La clase 'Num' no es una rareza, pero se podría argumentar razonablemente que' length' es un 'Int' en lugar de' Num a' es una peculiaridad. –

7

Citando LearnYouAHaskell.com:

Nota: Esta función tiene un tipo de numLongChains :: Int debido a la longitud devuelve un int en lugar de un Num a por razones históricas. Si quisiéramos devolver un Num a más general, podríamos haber usado de Integral en la longitud resultante.

Cuestiones relacionadas