апликативные котята
Jul. 20th, 2012 07:16 pmБеда с applicative functors на scala kittens с тем, что коряво выходит nesting разных функторов. Допустим, как обработать Stream[Option[Int]]?
Вот здесь попытался изложить по-другому.
1. "апликативные макбрайдовские скобочки" ограничивают контекст применения одного апликатива.
2. помочь с nesting
Многословно как-то.
1. не хочет хавать аргументы без скобочек: <* fs x y *> - никак не хочет
2. не умеет вывести тип аргументов: <* (fs) (_) (_) *> - вообще не умеет
3. нельзя просто взять и вызвать метод на результате апликатива: <* (fs) (x) (y) *> toList - совсем нельзя
Ну, хоть научился выводить тип функции без implicit аргумента. Потому что вот так работать не будет, если аргументов у as более одного:
Зато связка:
Вот здесь попытался изложить по-другому.
1. "апликативные макбрайдовские скобочки" ограничивают контекст применения одного апликатива.
2. помочь с nesting
object b extends Application {
class IsFunction[A,B,C]
implicit def isafunction[A,B]: IsFunction[A=>B,A,B] = null
final case class Pure[+A](val a: A)
final class Applicable[T[+_],+A,+C] (val apper: Applicative[T], val as: T[A]) {
def apply[B, _ >: A <: B=>Any](bs: T[B]):Applicable[T,C,C] = new Applicable(apper, apper.ap(as.asInstanceOf[T[B=>C]], bs))
def *>() : T[A] = as
}
implicit def applicablefunction[T[+_],A,B,C](as: Applicable[T,A,A])(implicit fs: IsFunction[A,B,C]) = as.asInstanceOf[Applicable[T,A,C]]
trait Applicative[T[+_]] { self =>
def pure[A](a: A): T[A]
def ap[A,B](fs: T[A=>B], as: T[A]): T[B]
// defining here, so that importing a particular Applicative enables the use of the "opening bracket"
// also, you can use the Applicative implementation name directly, which nicely explains the context eg. ZapList.<* ..... *>
def <*[A](as: T[A]): Applicable[T,A,A] = new Applicable[T,A,A](self, as)
def <*[A](a: Pure[A]): Applicable[T,A,A] = new Applicable[T,A,A](self, pure(a.a))
}
object ZapList extends Applicative[Seq] {
override def pure[A](a: A): Seq[A] = Stream.const(a)
override def ap[A,B](fs: Seq[A=>B], as: Seq[A]): Seq[B] = (fs zip as) map (p => p._1(p._2))
}
object ApOption extends Applicative[Option] {
override def pure[A](a: A): Option[A] = Some(a)
override def ap[A,B](fs: Option[A=>B], as: Option[A]): Option[B] = (fs, as) match {
case (Some(f),Some(x)) => Some(f(x))
case _ => None
}
}
import ZapList._
def pp(i: Int) = (j:Int) => i + j*j
val fs = Pure(pp _)
val fs_ = Seq(pp(1), pp(2))
val as = Seq(1, 2)
val bs = Seq(10,20,30)
println( <* (fs) *> )
println( <* (Pure(pp _)) apply (as) *> )
println( <* (fs_) *> )
println( <* (fs_) (bs) *> )
println( (<* (fs) (as) (bs) *>).toList )
println( <* (Pure(pp _)) (as) (bs) *>() toList )
// println( <* (as) (bs) *> ) // compilation error - correct!
val xs = Seq(Some(1), None, Some(2));
val ys = Seq(Some(10), Some(20), Some(30));
println( <* (Pure( (x:Option[Int]) => (y:Option[Int]) => ApOption.<* (fs) (x) (y) *> )) (xs) *> );
println( (<* (Pure( (x:Option[Int]) => (y:Option[Int]) => ApOption.<* (fs) (x) (y) *> )) (xs) (ys) *>).toList );
}Многословно как-то.
1. не хочет хавать аргументы без скобочек: <* fs x y *> - никак не хочет
2. не умеет вывести тип аргументов: <* (fs) (_) (_) *> - вообще не умеет
3. нельзя просто взять и вызвать метод на результате апликатива: <* (fs) (x) (y) *> toList - совсем нельзя
Ну, хоть научился выводить тип функции без implicit аргумента. Потому что вот так работать не будет, если аргументов у as более одного:
def apply[B, C](bs: T[B])(implicit fs: IsFunction[A,B,C]):Applicable[T,C,C] = ...
Зато связка:
final class Applicable[T[+_],+A,+C] (val apper: Applicative[T], val as: T[A]) {
def apply[B, _ >: A <: B=>Any](bs: T[B]):Applicable[T,C,C] = new Applicable(apper, apper.ap(as.asInstanceOf[T[B=>C]], bs))
def *>() : T[A] = as
}
implicit def applicablefunction[T[+_],A,B,C](as: Applicable[T,A,A])(implicit fs: IsFunction[A,B,C]) = as.asInstanceOf[Applicable[T,A,C]]позволяет делать implicit class cast Applicable[T,A,A] в Applicable[T,B=>C,C], т.е. выяснить тип результата, а apply() сделать применимым только в случае, когда тип A - это функция.