2010-12-06 16 views
6

Esta función funciona:Cómo devolver Data.Map de la función

serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num)) 

pero cuando atar:

serialExpansion :: Int -> Map 
serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num)) 

me sale el error:

simplifier.hs:46:26: Not in scope: type constructor or class `Map' 

Cómo debo declarar ¿la función?

Respuesta

12

Map es un tipo de datos parametrizado (también llamado abstract data type). Solo cuando especifica un tipo para las claves y un tipo para los valores obtiene un tipo completamente definido.

Por ejemplo, un mapa que le permite buscar String s por Integer s tiene el tipo Map Integer String.

Además, parece que importó Map calificado (como debería). Debido a esto, debe usar Map.Map en lugar de solo Map en la firma.

lo tanto, su función debe tener una firma como

serialExpansion :: Int -> Map.Map Key Value 

donde Key es el tipo de datos clave y Value es el tipo de datos de valor. En su caso, si tuviera que adivinar, tal vez desee Int para ambos Key y Value. Para ser precisos: quiere que Key sea el mismo que el tipo de los elementos en la lista listOfSimpleDividers num, y Value sea el mismo que el tipo de los elementos en la lista powers num. (Puede ser útil inspeccionar la firma de tipo Map.fromList si no está claro).

Por ahora puede que se pregunte: "pero si pudo decir el tipo de devolución correcto de serialExpansion, ¿por qué no puede el compilador?" Puede. Es exactamente por eso que funcionó tu primer ejemplo. Como omitió la firma de tipo, el compilador la dedujo del contexto. Como acaba de experimentar, escribir firmas de tipo puede ser una buena forma de asegurarse de comprender completamente su código (en lugar de confiar en la inferencia de tipo).

+0

¡El último párrafo es el punto clave! +1 – fuz

+2

Tipo de datos parametrizados (también llamado tipo de datos abstractos): "parametrizado" y "abstracto" no son lo mismo. Son conceptos independientes: un tipo de datos puede ser uno o ambos. – timbod

7

dos puntos para complementar la respuesta de GSPR:

Es una práctica común para importar el constructor de tipos Map sin reservas y luego importar el resto del módulo cualificado:

import Data.Map (Map) 
import qualified Data.Map as Map 

Esto le permite evitar escribir Map.Map en sus firmas de tipo en todas partes.

También, en GHCi o en Abrazos, puede usar :t para preguntar al entorno interactivo por el tipo inferido de cualquier función. Por ejemplo, si me carga este archivo en GHCi:

import Data.Map (Map) 
import qualified Data.Map as Map 

serialExpansion num = Map.fromList (zip (listOfSimpleDividers num) (powers num)) 
    where 
    powers = undefined 
    listOfSimpleDividers = undefined 

consigo el siguiente:

*Main> :t serialExpansion 
serialExpansion :: (Ord k) => t -> Map k a 

Si no conecta con sus propias definiciones de powers y listOfSimpleDividers obtendrá un tipo más específico.

0

Solo buscaba un mapa sin nada y luego agregarlo de una manera más flexible.

Si quiere hacer algo similar, necesita Map.empty (suponiendo que lo haya importado).

Cuestiones relacionadas