2010-11-25 11 views

Respuesta

3

Utilizando Monoid s o Numeric s para definir operaciones razonables para clases enriquecidas, utilizando implícitos si es necesario.

case class Money(ccy: Currency, amount : BigDecimal) { 
    def +(that : Money) = { 
    require(this.currency == that.curency) 
    copy(amount = this.amount + that.amount) 
    } 
    def abs = copy(amount = amount.abs) 
} 

Así que vamos a decir que tengo una colección de Money 's y quiero resumir ellos:

val turnover = trades.map(_.usdValue.abs).∑ //no implicit monoid :-(

Pero con el fin de hacer esto necesita tener una implícita Monoid. Pero, por supuesto, un cero valor para un Money solo tiene sentido si ya tengo alguna moneda.

implicit def CurrencyMonoid(implicit currency : Currency) = new Monoid[Currency] { 
    def zero = Money(currency, 0) 
    def append(m1 : Money, m2 : Money) = m1 + m2 
} 

Así que ahora Scala utilizarán ambos implícitos:

implicit val usd = Currency.USD 
val turnover = trades.map(_.usdValue.abs).∑ //yay for monoids :-) 
+0

Me gusta este el ¡más! Es mi pregunta, así que me permiten ser subjetivo :) –

3

Me perdí varias veces la forma de generar un producto cartesiano para las colecciones de Scala. En Haskell puede escribir

import Control.Applicative 
(,) <$> [1,2,3] <*> ["a","b"] 

-- [(1,"a"),(1,"b"),(2,"a"),(2,"b"),(3,"a"),(3,"b")] 

La solución Scala

for(x <- List(1,2,3); y <- List("a","b")) yield (x,y) 

es demasiado torpe.

+4

scalaz: '(Lista (1, 2, 3) | @ | Lista ("a", "b")) ((_, _)) ' – Debilski

+1

O scalaz:' (xs ⊛ ys) {× (_) (_)} 'si se trata de eso –

4

No es que esté golpeando el mismo tambor de nuevo, pero ...

Una solución para el problema en el que tenemos un número de procesos que pueden producir una salida exitosa, o no con algún mensaje de error. El objetivo es agregar los resultados exitosos, si todos los procesos producen un éxito y si uno o más fallan, agregar todos los mensajes de error.

Esto se puede resolver mediante scalaz validación: primer lugar, la configuración de algunas importaciones

scala> import scalaz._; import Scalaz._ 
import scalaz._ 
import Scalaz._ 

Ahora vamos a definir nuestros "procesos"

scala> def fooI(s : String) : ValidationNEL[Exception, Int] = s.parseInt.liftFailNel 
fooI: (s: String)scalaz.Scalaz.ValidationNEL[Exception,Int] 

scala> def fooF(s : String) : ValidationNEL[Exception, Float] = s.parseFloat.liftFailNel 
fooF: (s: String)scalaz.Scalaz.ValidationNEL[Exception,Float] 

scala> def fooB(s : String) : ValidationNEL[Exception, Boolean] = s.parseBoolean.liftFailNel 
fooB: (s: String)scalaz.Scalaz.ValidationNEL[Exception,Boolean] 

Ahora usa Applicative para agregar los fallos/éxitos:

scala> def attempt(ss : String*) = (fooI(ss(0)) <|**|> (fooF(ss(1)), fooB(ss(2)))) match { 
| case Success((i, f, b)) => println("Found " + i + " " + f + " " + b) 
| case Failure(es)  => es foreach println 
| } 
attempt: (ss: String*)Unit 

Ahora vamos a tratar de algunos fallos:

scala> attempt("a", "b", "true") 
java.lang.NumberFormatException: For input string: "a" 
java.lang.NumberFormatException: For input string: "b" 

Ahora vamos a probar para el éxito:

scala> attempt("1", "2.3", "false") 
Found 1 2.3 false 
2

Si cierta condición cond mantiene volver Some(x) o regrese None:

Some(x) filter cond 

[ recogido de la publicación de Paul Phillips en la lista de correo]

3

robado Desvergonzadamente de respuesta oxbow_lakes' a esta pregunta: Instantiating a case class from a list of parameters

Llamar a un método/función utilizando una tupla para suministrar los argumentos:

case class Foo(a: Int, b: String, c: Double) 
(Foo.apply _).tupled apply (1, "bar", 3.14) 

Esto se puede utilizar para cualquier función.

1

A veces hay que utilizar, mientras que en lugar de para, y la frecuencia con la que son resultados recepción:

val buf = new Listbuffer[Int] 
while(cond()) { 
    val x = fancyStuff() 
    buf += calculation(x) 
} 

creo Sería muy útil tener para while la misma posibilidad de "ceder" algo que para for, eliminando algunas rebabas en el borde entre imperativo y funct ional estilo:

val buf = while(cond()) { 
    val x = fancyStuff() 
} yield calculation(x) 
Cuestiones relacionadas