Trovo molto comune voler modellare i dati relazionali nei miei programmi funzionali. Ad esempio, quando lo sviluppo di un sito web mi può essere utile avere la seguente struttura dei dati per memorizzare informazioni sui miei utenti:Modellazione sicura dei dati relazionali in Haskell
data User = User
{ name :: String
, birthDate :: Date
}
Avanti, voglio memorizzare i dati sui messaggi utenti post sul mio sito:
data Message = Message
{ user :: User
, timestamp :: Date
, content :: String
}
ci sono molteplici problemi associati a questa struttura di dati:
- non abbiamo alcun modo di distinguere gli utenti con nomi simili e date di nascita.
- I dati dell'utente verranno duplicati in caso di serializzazione/deserializzazione
- Il confronto degli utenti richiede il confronto dei dati che possono essere un'operazione costosa.
- Gli aggiornamenti nei campi di
User
sono fragili: è possibile dimenticare di aggiornare tutte le occorrenze diUser
nella struttura dei dati.
Questi problemi sono gestibili mentre i nostri dati possono essere rappresentati come un albero. Ad esempio, è possibile refactoring in questo modo:
data User = User
{ name :: String
, birthDate :: Date
, messages :: [(String, Date)] -- you get the idea
}
Tuttavia, è possibile avere i dati a forma di DAG (immaginare una relazione molti-a-molti), o anche come un grafico generale (OK, forse non). In questo caso, tendo a simulare il database relazionale per la memorizzazione dei miei dati in Map
s:
newtype Id a = Id Integer
type Table a = Map (Id a) a
Questo tipo di opere, ma è pericoloso e brutto per molteplici ragioni:
- Tu sei solo un Chiamata del costruttore
Id
lontano da ricerche senza senso. - Nella ricerca si ottiene
Maybe a
, ma spesso il database garantisce strutturalmente che esista un valore. - È impacciato.
- È difficile garantire l'integrità referenziale dei dati.
- Gestire gli indici (che sono molto necessari per le prestazioni) e garantire la loro integrità è ancora più difficile e più clamoroso.
Esiste già un lavoro per superare questi problemi?
Sembra che Template Haskell possa risolverli (come al solito), ma mi piacerebbe non reinventare la ruota.
non il modello mostrato qui condividere tutti gli svantaggi uno-a-molti del modello originale dalla domanda? – ehird
@ehird, faccio circa 10 modifiche al minuto, quindi penso di aver risposto alla tua preoccupazione lungo la strada. – dflemstr
Sì, davvero. (BTW, lo stato acido non dipende in realtà da ixset, sono solo progettati per essere usati insieme.) – ehird