2012-04-11 11 views
23

decir que tengo el siguiente tipo de datos personalizado y función en Haskell:miembros de Acceso de un tipo de datos personalizado en Haskell

data Person = Person { first_name :: String, 
         last_name :: String, 
         age :: Int 
        } deriving (Eq, Ord, Show) 

Si quiero crear una función print_age para imprimir la edad de una persona, de este modo: print_age (Person "John" "Smith" 21) , ¿cómo escribiría print_age para acceder al parámetro de edad? Soy un chico orientado a objetos, así que estoy fuera de mi elemento aquí. Básicamente estoy buscando el equivalente de Person.age.

Respuesta

37

La aplicación de función es prefijo, por lo que age person correspondería al person.age() común en lenguajes OOP. La función print_age podría definirse pointfree por la composición de funciones

print_age = print . age 

o punto completo

print_age person = print (age person) 
16

Esto se llama sintaxis de registro, LYAH has a good section on it (ctrl-f para "sintaxis Record").

Cuando un tipo de datos se define con los registros, Haskell define automáticamente funciones con el mismo nombre que el registro para actuar como descriptores de acceso, por lo que en este caso age es el descriptor de acceso para el campo de la edad (que tiene el tipo Person -> Int), y lo mismo para first_name y last_name.

Estas son funciones normales de Haskell, por lo que se llaman como age person o first_name person.

+0

En Frege (Haskell para la JVM) un registro presenta un espacio de nombres, por lo que iba a escribir '' 'Person.age person'''. Por otro lado, Frege permite escribir '' 'person.age''', al igual que en OO. – 0dB

+1

Como una nueva (!) Newbee, estoy descubriendo que el desorden del espacio de nombres producido por los registros es feo y frustrante. La sintaxis de Frege es atractiva y, iiuc, evita este problema. – Alan

+0

Ah, veo que no estoy solo: https://ghc.haskell.org/trac/ghc/wiki/Records/NameSpacing – Alan

4

Además de la función age mencionada en otras respuestas, a veces es conveniente usar la coincidencia de patrones.

print_age Person { age = a } = {- the a variable contains the person's age -} 

Hay una extensión bastante inocua que le permite saltar el bit de nombres:

{-# LANGUAGE NamedFieldPuns #-} 
print_age Person { age } = {- the age variable contains the person's age -} 

... y otro, visto con diferentes grados de desconfianza por varios miembros de la comunidad, lo que le permite incluso saltarse dicho los campos que desea poner en alcance:

{-# LANGUAGE RecordWildCards #-} 
print_age Person { .. } = {- first_name, last_name, and age are all defined -} 
Cuestiones relacionadas