scalaz/scalaz — pull request #175 by eed3si9n (2012-10-28 06:51:43+00:00)
Title: HListFunc (Composition of functor functions)

This is an improvement to #161, which implemented `Func`.

`AppFunc` data type implemented `@&&&` method to composite two applicative functions producing another function that returns `Tuple2[F, G]`. @larsrh suggested I use `typelevel` package, and thus `Func` was created to handle several typeclasses generically. `@&&&` was refactored to use `HList`, but it remained to handle only two items at a time.

## What this changes

As per @larsrh's suggestion, this provides composition that produces function that returns n-item `HList`.

```scala
scala> import scalaz._, scalaz.std.AllInstances._, typelevel._, Func._
import scalaz._
import scalaz.std.AllInstances._
import typelevel._
import Func._

scala> AppFuncU { (x: Int) => x + 1 } :: AppFuncU { (x: Int) => List(x, 5) } :: AppFunc.HNil
res0: scalaz.typelevel.HListFunc[scalaz.typelevel.TCCons[scalaz.Unapply[scalaz.Applicative,Int]{type M[X] = Int; type A = Int}#M,scalaz.typelevel.TCCons[scalaz.Unapply[scalaz.Applicative,List[Int]]{type M[X] = List[X]; type A = Int}#M,scalaz.typelevel.TCNil]],scalaz.Applicative,Int,Int] = scalaz.typelevel.Func$$anon$4@538f7b25

scala> res0.runA(10)
res1: scalaz.typelevel.TCCons[scalaz.Unapply[scalaz.Applicative,Int]{type M[X] = Int; type A = Int}#M,scalaz.typelevel.TCCons[scalaz.Unapply[scalaz.Applicative,List[Int]]{type M[X] = List[X]; type A = Int}#M,scalaz.typelevel.TCNil]]#Product[Int] = GenericCons(11,GenericCons(List(10, 5),GenericNil()))

scala> res0 traverse List(1, 2, 3)
res2: scalaz.typelevel.TCCons[scalaz.Unapply[scalaz.Applicative,Int]{type M[X] = Int; type A = Int}#M,scalaz.typelevel.TCCons[scalaz.Unapply[scalaz.Applicative,List[Int]]{type M[X] = List[X]; type A = Int}#M,scalaz.typelevel.TCNil]]#Product[List[Int]] = GenericCons(9,GenericCons(List(List(1, 2, 3), List(1, 2, 5), List(1, 5, 3), List(1, 5, 5), List(5, 2, 3), List(5, 2, 5), List(5, 5, 3), List(5, 5, 5)),GenericNil()))
```