Il nome del pacchetto, i tag del pacchetto ei nomi dei moduli sono tutte cose indipendenti.
Il nome del pacchetto è un identificatore arbitrario (purché non sia in conflitto con nessun altro). È convenzionale per rendere tutto in minuscolo con trattini tra le parole. Se diversi pacchetti fanno parte di una famiglia, il formato è ad es. "llvm-base" con il nome della famiglia prima. Secondo il manuale del pacchetto Cabal, i nomi possono contenere lettere, numeri e trattini, ma non spazi. Non conosco altri segni di punteggiatura, ma lo eviterei anche se Cabal lo lascia passare. Inoltre, grazie alle diverse regole sulle lettere maiuscole nei nomi di percorso tra Windows e Linux ci può essere confusione, quindi è meglio attenersi alle minuscole.
I tag vengono utilizzati per aiutare i siti come Hackage a organizzare l'elenco di pacchetti in gruppi utili e non hanno altro significato.
All'interno di un pacchetto ci saranno uno o più moduli. Questi sono ciò che verrà importato dal codice sorgente del client. I moduli esistono in uno spazio dei nomi gerarchico. Ad esempio, il pacchetto "parsec" include un modulo "Text.Parsec.Combinator". Puoi pensare ai punti come a Linux "/" in un nome di percorso (e infatti la sorgente sarà in un file in "src/Text/Parsec/Combinator.hs").
Esistono alcuni nomi di moduli convenzionali di livello superiore, come "Controllo", "Dati", "Testo" e "Sistema", che è possibile utilizzare in base al lavoro principale del modulo. È buono da usare, ma non obbligatorio. L'aspetto del nome del pacchetto nel nome del modulo (ad esempio "Parsec") è presente solo per evitare conflitti di nomi; non esiste una relazione formale tra il nome del pacchetto e i moduli che contiene.
È possibile avere un pacchetto con moduli in diverse gerarchie di primo livello. Ad esempio potresti avere un pacchetto contenente "System.Foo" e "Data.Foo".
"Controllo" in senso lato viene utilizzato per le monadi e roba correlata, in particolare i combinatori di frecce e monadi. Ma dal momento che una monade è anche un tipo di dati, non dovresti sentire la necessità di inserire un tipo monadico in un modulo separato solo per farlo entrare in "Controllo".
"Dati" è un catch-all. In caso di dubbio, inseriscilo in Dati.
"Sistema" viene utilizzato per i servizi del sistema operativo, specialmente quelli che potrebbero non essere portatili.
"Testo" viene utilizzato per manipolare il testo, l'analisi, la stampa e così via. Qualsiasi cosa con molte manipolazioni di stringhe probabilmente appartiene qui.
"Grafica": ovviamente.
È facoltativo avere un nome di modulo a un livello e quindi altri moduli sotto di esso. Quindi "Text.Parsec" è un modulo, e lo è anche "Text.Parsec.Combinators", ma il progettista di Parsec non ha bisogno di includere "Text.Parsec". Quando ciò viene fatto, di solito significa che il modulo di livello superiore (in questo caso "Text.Parsec") esporta un sottoinsieme comune dei suoi moduli figli, quindi in molti casi il codice client deve solo importare "Text.Parsec" anziché tutta la famiglia.
https://www.haskell.org/cabal/proposal/x138.html ci dice che "Ogni pacchetto ha un nome di pacchetto globalmente unico, senza spazi. [...] Come vengono distribuiti i nomi dei pacchetti univoci non fa parte di questa specifica [...]. " ma c'è anche https://wiki.haskell.org/Hierarchical_module_names – gxtaillon
Non so se c'è una guida scritta. Credo che molti sviluppatori scelgano il punto nell'attuale gerarchia di hacker in cui sono state trovate le librerie più simili. Ovviamente, esistono delle eccezioni: ad es. 'Web' potrebbe essere stato' Network.Web'. – chi
Alcune lingue (ad es. Java) spingono gli sviluppatori a utilizzare spazi dei nomi separati come in "nome produttore.a.b.c". In Haskell questa convenzione non è sicuramente seguita: ogni pacchetto solitamente innesta i suoi moduli nella gerarchia esistente. – chi