Mettendo da parte i dettagli di implementazione per un momento, map
èandThen
per le funzioni (sotto l'istanza functor per A => ?
), e in realtà non fanno un sacco di senso parlare di preferire l'uno rispetto all'altro se parliamo di funzioni specifiche e non di un livello più alto di astrazione.
Quali metodi come(e tipo classi come Functor
in genere) ci consentono di fare astratti su tipi specifici o costruttori di tipi. Supponiamo di voler scrivere un metodo incrementResult
che funzioni sia su A => Int
sia su Kleisli[Option, A, Int]
, ad esempio. Questi tipi non hanno nulla in comune in termini di eredità (a corto di AnyRef
, che è inutile), ma A => ?
e Kleisli[Option, A, ?]
sono entrambi funtori, così abbiamo potuto scrivere questo:
import scalaz._, Scalaz._
def incrementResult[F[_]: Functor](f: F[Int]): F[Int] = f.map(_ + 1)
e quindi utilizzarlo come questo (notare che io sto usando kind-projector per semplificare la sintassi di tipo un po '):
scala> val plainOldFuncTriple: Int => Int = _ * 3
plainOldFuncTriple: Int => Int = <function1>
scala> val optionKleisliTriple: Kleisli[Option, Int, Int] = Kleisli(i => Some(i * 3))
optionKleisliTriple: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>)
scala> val f = incrementResult[Int => ?](plainOldFuncTriple)
f: Int => Int = <function1>
scala> val k = incrementResult[Kleisli[Option, Int, ?]](optionKleisliTriple)
k: scalaz.Kleisli[Option,Int,Int] = Kleisli(<function1>)
scala> f(10)
res0: Int = 31
scala> k(10)
res1: Option[Int] = Some(31)
In questo caso specifico ci sono modi migliori per attuare questa operazione, ma si vede il generale idea-non siamo riusciti a scrivere un metodo singolo che funziona sia per le funzioni ordinarie che per le frecce di Kleisli utilizzando andThen
, ma possiamo con il livello extra di astrazione che ci offre map
.
Quindi per rispondere alla tua domanda uso-un'affermazione da map
se si desidera astratto su tutti i costruttori di tipo che hanno un esempio funtore, ma se si sta lavorando in particolare con le funzioni, map
èandThen
, e-il più a lungo dato che stiamo ancora mettendo da parte i dettagli di implementazione, non importa quale scegli.
Nota: il map
che il pacchetto di Scalaz syntax
si dà per valori di tipi che hanno casi funtore è implementato come un metodo di estensione, quindi c'è un po 'di testa (sia in fase di compilazione e di runtime) che comporta l'utilizzazione map
anziché andThen
su una funzione. Se lavori solo con le funzioni e non hai bisogno di astrazione extra, allora potresti anche andare con andThen
.
Ben 'map' funziona su qualsiasi funtore, non solo su funzioni. – Bergi
Ci stavo pensando anch'io. Quindi posso mappare un elenco di opzioni e un elenco di functor ma non riesco a capire come creare un elenco di funtori. – thlim