2012-06-07 5 views
9

Stavo cercando di convertire un esempio di haskell, mi sono imbattuto prima, in scalaz. L'esempio originale era questo:Istanza applicativa per una tupla con monoide e funzione all'interno di

("Answer to the ", (*)) <*> ("Ultimate Question of ", 6) <*> ("Life, the Universe, and Everything", 7) 

Il che, per quanto io sono in grado di capire, usa this esempio.

non venga convertito in scalaz letteralmente:

scala> ("Answer to the ", ((_: Int) * (_: Int)) curried) |@| ("Ultimate Question of ", 6) |@| ("Life, the Universe, and Everything", 7) tupled 
res37: (java.lang.String, (Int => (Int => Int), Int, Int)) = (Answer to the Ultimate Question of Life, the Universe, and Everything,(<function1>,6,7)) 

Anche se, ho cercato per un'istanza, e sembra be there (ancora una volta, per quanto sono in grado di capire).

Quindi, la domanda è: perché non funziona così? O cosa mi sono perso/non ho ottenuto correttamente?

+1

Questo codice invia effettivamente all'istanza applicativa per le tuple. Che a sua volta usa il 'mappend' monoid per le liste (concatenazione). Quindi è la composizione di funzione del 2 ° componente della tupla, con la concatenazione di lista della prima parte. –

risposta

5

L'equivalente di Scalaz di Control.Applicative<*> viene anche chiamato <*>, anche se in modo confuso prende i suoi argomenti nell'ordine opposto. Così le seguenti opere:

val times = ((_: Int) * (_: Int)) curried 
val a = "Answer to the " 
val b = "Ultimate Question of " 
val c = "Life, the Universe, and Everything" 

(c, 7) <*> ((b, 6) <*> (a, times)) 

O, come ho notato in risposta al tuo commento, è possibile utilizzare il seguente se si vuole attaccare con |@|:

(a -> times |@| b -> 6 |@| c -> 7)(_ apply _ apply _) 

Io personalmente preferisco il <*> versione, anche se si sente indietro.


Possiamo vedere cosa sta succedendo un po 'più in dettaglio. Prima di tutto, non hai bisogno della piena potenza di Applicative qui- Apply farà. Siamo in grado di ottenere l'istanza Apply per le tuple utilizzando implicitly:

scala> val ai = implicitly[Apply[({type λ[α]=(String, α)})#λ]] 
ai: scalaz.Apply[[α](java.lang.String, α)] = [email protected] 

Ora possiamo applicare il nostro primo tuple alla seconda:

scala> :t ai(a -> times, b -> 6) 
(java.lang.String, Int => Int) 

E il risultato al terzo:

scala> :t ai(ai(a -> times, b -> 6), c -> 7) 
(java.lang.String, Int) 

Che è quello che vogliamo:

scala> ai(ai(a -> times, b -> 6), c -> 7)._1 
res0: java.lang.String = Answer to the Ultimate Question of Life, the Universe, and Everything 

scala> ai(ai(a -> times, b -> 6), c -> 7)._2 
res1: Int = 42 

Il metodo <*> su MA avvolge leggermente questo aspetto.

+0

Grazie, funziona come dovrebbe. A proposito, hai qualche idea, come farlo con l'ApplicativeBuilder e se sembrerà meglio in questo modo? – folone

+1

Certo, si potrebbe fare qualcosa come '(a -> times | @ | b -> 6 | @ | c -> 7) (_ apply _ apply _)', ma penso che la versione '<*>' sia più bella. –

+0

Sì, funziona. Sono stato indotto in errore dal fatto che "tupla" ha incollato il monoide, quindi ho pensato che avrebbe applicato anche la funzione. – folone

Problemi correlati