2012-04-11 17 views
23

dire che ho il seguente tipo di dati personalizzati e la funzione in Haskell:Accesso membri di un tipo di dati personalizzati a Haskell

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

Se voglio creare una funzione print_age per stampare l'età di una persona, in questo modo: print_age (Person "John" "Smith" 21) , come potrei scrivere print_age per accedere al parametro age? Sono un ragazzo orientato agli oggetti, quindi sono fuori dal mio elemento qui. Sto fondamentalmente cercando l'equivalente di Person.age.

risposta

37

L'applicazione funzione è il prefisso, quindi age person corrisponde al person.age() comune nei linguaggi OOP. La funzione print_age potrebbe essere definita da pointfree funzione composizione

print_age = print . age 

o punto-full

print_age person = print (age person) 
16

Questo è chiamato sintassi record LYAH has a good section on it (Ctrl-f per "sintassi Record").

Quando un tipo di dati viene definito con i record, Haskell definisce automaticamente funzioni con lo stesso nome del record di agire come di accesso, quindi in questo caso age è la funzione di accesso per il campo di età (che ha tipo Person -> Int), e analogamente per first_name e last_name.

Queste sono normali funzioni Haskell e quindi sono chiamate come age person o first_name person.

+0

In Frege (Haskell per la JVM) un record introduce uno spazio dei nomi, quindi si può scrivere '' 'Person.age person'''. D'altra parte, Frege permette di scrivere '' 'person.age''', proprio come in OO. – 0dB

+1

Come newbee completo (!), Trovo che il disordine dello spazio dei nomi prodotto dai record sia brutto e frustrante. La sintassi di Frege è attraente e, iiuc, evita questo problema. – Alan

+0

Ah, vedo che non sono solo: https://ghc.haskell.org/trac/ghc/wiki/Records/NameSpacing – Alan

4

Oltre alla funzione age menzionata in altre risposte, a volte è conveniente utilizzare la corrispondenza del modello.

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

C'è un'estensione abbastanza innocuo che permette di saltare il bit di denominazione:

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

... e un altro, visto con vari gradi di diffidenza da vari membri della comunità, che consente di anche saltare detto quali campi si desidera mettere in campo di applicazione:

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