Cebirde, günlük kavram oluşumunda olduğu gibi, soyutlamalar, nesneleri bazı temel özelliklere göre gruplandırarak ve onların belirli diğer özelliklerini çıkararak oluşturulur. Soyutlama, benzerlikleri ifade eden tek bir sembol veya kelime altında birleştirilir. Farklılıkları soyutladığımızı söylüyoruz , ancak bu gerçekten benzerliklerle bütünleştiğimiz anlamına geliyor .
Örneğin, sayıların toplamını alır bir program düşünün 1
, 2
ve 3
:
val sumOfOneTwoThree = 1 + 2 + 3
Bu program, çok soyut olmadığı için çok ilginç değil. Biz can üzerinde soyut bir tek sembolü altında sayıların tüm listeleri entegre ederek, toplayarak konum numaraları ns
:
def sumOf(ns: List[Int]) = ns.foldLeft(0)(_ + _)
Ve bunun bir Liste olması da umurumuzda değil. Liste, belirli bir tür kurucusudur (bir tür alır ve bir tür döndürür), ancak hangi temel özelliği istediğimizi (katlanabileceğini) belirleyerek tür oluşturucuyu soyutlayabiliriz :
trait Foldable[F[_]] {
def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
}
def sumOf[F[_]](ns: F[Int])(implicit ff: Foldable[F]) =
ff.foldl(ns, 0, (x: Int, y: Int) => x + y)
Ve katlayabileceğimiz herhangi bir şey Foldable
için örtük örneklerimiz List
olabilir.
implicit val listFoldable = new Foldable[List] {
def foldl[A, B](as: List[A], z: B, f: (B, A) => B) = as.foldLeft(z)(f)
}
val sumOfOneTwoThree = sumOf(List(1,2,3))
Dahası , işlenenlerin hem işleyişi hem de türü hakkında özetleyebiliriz :
trait Monoid[M] {
def zero: M
def add(m1: M, m2: M): M
}
trait Foldable[F[_]] {
def foldl[A, B](as: F[A], z: B, f: (B, A) => B): B
def foldMap[A, B](as: F[A], f: A => B)(implicit m: Monoid[B]): B =
foldl(as, m.zero, (b: B, a: A) => m.add(b, f(a)))
}
def mapReduce[F[_], A, B](as: F[A], f: A => B)
(implicit ff: Foldable[F], m: Monoid[B]) =
ff.foldMap(as, f)
Şimdi oldukça genel bir şeyimiz var. Yöntem mapReduce
, bunun katlanabilir olduğunu ve bunun bir monoid olduğunu veya bir tanede eşlenebileceğini F[A]
kanıtlayabildiğimiz herhangi bir veriyi katlayacaktır. Örneğin:F
A
case class Sum(value: Int)
case class Product(value: Int)
implicit val sumMonoid = new Monoid[Sum] {
def zero = Sum(0)
def add(a: Sum, b: Sum) = Sum(a.value + b.value)
}
implicit val productMonoid = new Monoid[Product] {
def zero = Product(1)
def add(a: Product, b: Product) = Product(a.value * b.value)
}
val sumOf123 = mapReduce(List(1,2,3), Sum)
val productOf456 = mapReduce(List(4,5,6), Product)
Biz var üzerinde soyutlanmış Monoidler ve foldables.