2013-05-31 14 views
8

Ieri sera nel rispondere alle this question, ho notato quanto segue:Impostare il tipo di sequenza di puzzle

scala> val foo: Option[Set[Int]] = Some(Set(1, 2, 3)) 
foo: Option[Set[Int]] = Some(Set(1, 2, 3)) 

scala> import scalaz._, Scalaz._ 
import scalaz._ 
import Scalaz._ 

scala> foo.sequenceU 
res0: scala.collection.immutable.Set[Int] = Set(1, 2, 3) 

Cioè, se foo è un set opzionale di numeri interi, sequenziamento restituisce un insieme di numeri interi.

Questo non è quello che mi aspettavo in un primo momento, dal momento che il sequenziamento di un F[G[A]] dovrebbe restituire un G[F[A]] (supponendo che F è attraversabile e Gis an applicative functor). In questo caso, tuttavia, il livello Option scompare.

So che questo probabilmente ha qualcosa a che fare con qualche interazione tra uno dei supertipi di Set e la macchina che fa UnapplysequenceU il lavoro, e quando posso trovare qualche minuto ho intenzione di lavorare attraverso i tipi e scrivere una descrizione di cosa sta succedendo.

Sembra un piccolo rompicapo potenzialmente interessante, tuttavia, e ho pensato di pubblicarlo qui nel caso qualcuno mi potesse battere per una risposta.

risposta

7

wow, si. Ecco cosa posso immaginare sta succedendo. poiché Set non ha un applicativo propria, stiamo ottenendo il Monoide # applicativa esempio invece:

scala> implicitly[Unapply[Applicative, Set[Int]]].TC 
res0: scalaz.Applicative[_1.M] forSome { val _1: scalaz.Unapply[scalaz.Applicative,Set[Int]] } = [email protected] 

Dal Monoide è definito per i tipi di tipo * e applicativo è definito per i tipi di tipo * -> * , la definizione di applicativo in Monoide incunea sorta in un parametro di tipo ignorato utilizzando un tipo lambda:

final def applicative: Applicative[({type λ[α]=F})#λ] = new Applicative[({type λ[α]=F})#λ] with SemigroupApply... 

Avviso lì che il parametro di tipo α di λ viene gettato via, in modo che quando applicativo punto # è chiamato, che diventa Monoide #zero, invece di essere un mono [Set [Option [Int]]] è un mono [Set [Int]].

Larsh sottolinea che questo ha l'interessante effetto collaterale di alllowing sequenceU essere (ab) usato come somma:

scala> List(1,2,3).sequenceU 
res3: Int = 6 
Problemi correlati