2012-04-24 6 views
6

Dado un tipo de ejemplo de datos con la sintaxis de registro:coincidencia de patrones vs función sintaxis de registro para la extracción de campo de tipo de datos

data VmInfo = VmInfo {infoVid :: String 
        ,infoIndex :: Int 
        ,infoPid :: Int 
        ,infoExe :: String 
        } deriving (Show) 

y (vminfo :: string -> vminfo) función que genera y devuelve la estructura de datos antes indicados vm nombre como cadena.

Veo dos métodos para extraer las partes individuales del tipo de datos VmInfo.

(VmInfo vid _ _ _) <- vmInfo vm 

Cual es solo una coincidencia de patrón. Y ...

vid <- infoVid <$> vmInfo vm 

utilizando las funciones generadas del compilador de sintaxis de registro.

La pregunta es simple: ¿cuál es el método preferido?

En cuanto a la cantidad de tipeo, son los mismos, así que estoy buscando velocidad y corrección/mejor práctica.

Supongo que la coincidencia de patrón sería más rápida, pero ¿cuál es el punto de sintaxis de registro?

Gracias.

+1

Creo que la sintaxis del registro se convierte en la versión de coincidencia de patrones del compilador, por lo que no habrá diferencia de velocidad. – ricochet1k

Respuesta

8

Estos no son semánticamente equivalentes. mirada

Vamos en el primer ejemplo:

(VmInfo vid _ _ _) <- vmInfo vm 

Esto realiza una comparación de patrones en la operación de unión. Hay dos resultados de esto. El primero es que se evalúa el constructor del resultado de la acción vmInfo vm. Esto significa que si vmInfo terminara con una línea como return undefined, la excepción arrojada al evaluar undefined ocurriría en esta coincidencia de patrón, no en un uso posterior de vid. El segundo es que si se refuta la coincidencia de patrón (la coincidencia de patrón no coincide con el valor), se llamará a la instancia de la mónada fail con el texto de error de coincidencia de patrón. Eso no es posible en este caso, pero generalmente es posible cuando el patrón coincide con un constructor en un enlace.

Ahora, con el siguiente ejemplo:

vid <- infoVid <$> vmInfo vm 

Por la definición de <$>, esto será totalmente perezoso en el valor devuelto por la acción (no los efectos). Si vmInfo finalizó con return undefined, no obtendría la excepción al evaluar undefined hasta que haya hecho algo que haya utilizado el valor de vid. Además, si infoVoid tuviera la capacidad de lanzar cualquier excepción, no terminarían sucediendo hasta el uso de vid, el mejor de los casos.

Curiosamente, estas diferencias solo están presentes en el alcance de un enlace monádico. Si vmInfo era puro y estaba vinculando el nombre vid dentro de una expresión let o where, generarían un código idéntico.

En ese caso, cuál desearía usar es totalmente suya. Ambos son idiomáticos Haskell. La gente generalmente elige la que se ve mejor en el contexto en el que están trabajando.

La razón principal por la que las personas usan las funciones de acceso es la brevedad cuando el registro tiene tantos campos que una coincidencia de patrón es enorme, y porque son funciones reales, se pueden pasar a cualquier función de orden superior en su tipo. No puede pasar las coincidencias de patrones como una construcción distinta.

+6

Otra razón para usar los descriptores de acceso sobre la coincidencia de patrones es hacer que el código sea un poco más robusto contra el cambio de la estructura de datos a medida que se mantiene el programa. Si cambia una estructura de datos de casi cualquier forma, normalmente todas las coincidencias de patrones no podrán compilarse. Si solo está tratando con un pequeño número de campos a la vez en un tipo con muchos campos, el uso de accesores significa que las modificaciones en la estructura de datos tienen una buena probabilidad de afectar principalmente a los lugares que usan los campos que ha agregado./eliminado/cambiado. – Ben

+6

@Ben Para obtener las ventajas de ambos, 'VmInfo {infoVid = vid} <- vmInfo vm'. –

Cuestiones relacionadas