2014-07-15 27 views
5

Attualmente sto eseguendo il porting di un codice dallo stile tradizionale Scala a Scalaz.Scalaz Bind [Seq] typeclass

E 'abbastanza comune attraverso la maggior parte del mio codice per utilizzare il tratto Seq nelle mie firme API esposte piuttosto che un tipo concreto (cioè List, Vector) direttamente. Tuttavia, ciò pone alcuni problemi con Scalaz, poiché non fornisce un'implementazione di una classe di tipi Bind [Seq].

Ad esempio, funzionerà correttamente.

List(1,2,3,4) >>= bindOperation 

Ma questo non

Seq(1,2,3,4) >>= bindOperation 

sarà mancato con l'errore could not find implicit value for parameter F0: scalaz.Bind[Seq]

Presumo che ciò è una decisione di progettazione intenzionale Scalaz - tuttavia sono incerti circa destinato migliori pratiche/su come precedere .

Dovrei invece scrivere il mio codice direttamente a/Elenco di vettore a seconda dei casi, invece di utilizzare l'interfaccia più flessibile Seq? O dovrei semplicemente definire la mia propria classe Bind [Seq]?

+1

C'è un'istanza monad di 'IndexedSeq', però. – rightfold

risposta

11

La biblioteca collezioni fa salti mortali per accogliere sottotipizzazione: quando si utilizza map su un tipo specifico di raccolta (l'elenco, carta, ecc), si (di solito) ottiene lo stesso tipo di nuovo. Gestisce questo tramite l'uso di an extremely complex inheritance hierarchy insieme a classi di tipi come CanBuildFrom. Ottiene il lavoro fatto (almeno discutibilmente), ma la complessità non si sente molto basata sui principi. È un disastro. Molte persone lo odiano.

La complessità è generalmente abbastanza facile da evitare come un utente della biblioteca, ma per un progettista libreria è un incubo. Se fornisco un'istanza monad per Seq, ciò significa che tutti i tipi dei miei utenti hanno eseguito il bump della gerarchia su Seq ogni tipo che usano un'operazione monadica.

Scalaz persone tendono a non piace sottotipizzazione molto, comunque, quindi per la maggior parte Scalaz rimane intorno le foglie della Gerarchia, List, Vector, ecc Potete vedere qualche discussione di questa decisione on the mailing list, per esempio.

Quando ho iniziato ad usare Scalaz Ho scritto un sacco di codice di utilità che ha cercato di fornire le istanze per Seq, ecc e renderli utilizzabili con CanBuildFrom. Poi ho smesso e ora tendo a seguire Scalaz in sempre e solo usando List, Vector, Map e Set nel mio codice. Se siete impegnati a "stile Scalaz", si dovrebbe fare anche questo (o anche adottare Scalaz propria IList, ISet, ==>>, etc.). Non troverai un chiaro accordo sulle migliori pratiche in generale, però, e entrambi gli approcci possono essere fatti funzionare, quindi dovrai solo sperimentare per trovare quello che preferisci.

+1

È anche questo il motivo, ad es. 'scalaz.NonEmptyList [T]' non è un sottotipo di 'Seq [T]'? – rightfold

+1

@rightfold: Sì, e non sarei troppo sorpreso se 'NonEmptyList' diventasse invariante un giorno, che è un'altra ragione per non rimanere bloccati nella palude di' Seq'. –