Created
September 28, 2017 15:00
-
-
Save neutropolis/0d8e74285d7b4ec2349190ebe3056985 to your computer and use it in GitHub Desktop.
Toying around with indexed traversals in Monocle
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package monocle | |
import scalaz._, Scalaz._ | |
import Indexable._ | |
abstract class IPTraversal[I, S, T, A, B] { | |
def modifyF[ | |
F[_]: Applicative, | |
P[_, _]: Indexable[I, ?[_, _]]]( | |
f: P[A, F[B]])(s: S): F[T] | |
def getAll(s: S): List[(I, A)] = | |
modifyF[Const[List[(I, A)], ?], Indexed[I, ?, ?]]( | |
Indexed(i => a => Const(List((i, a)))))(s).getConst | |
def modify(f: I => A => B)(s: S): T = | |
modifyF[Id, Indexed[I, ?, ?]](Indexed(f))(s) | |
} | |
object IPTraversal { | |
def both[A, B] = new IPTraversal[Boolean, (A, A), (B, B), A, B] { | |
def modifyF[ | |
F[_]: Applicative, | |
P[_, _]: Indexable[Boolean, ?[_, _]]]( | |
f: P[A, F[B]])(s: (A, A)): F[(B, B)] = | |
index(f)(true)(s._1).tuple(index(f)(false)(s._2)) | |
} | |
} | |
trait Indexable[I, P[_, _]] { | |
def index[A, B](pab: P[A, B])(i: I)(a: A): B | |
} | |
object Indexable { | |
implicit def functionIndexable[I]: Indexable[I, ? => ?] = | |
new Indexable[I, ? => ?] { | |
def index[A, B](f: A => B)(i: I)(a: A) = f(a) | |
} | |
case class Indexed[I, A, B](runIndexed: I => A => B) | |
implicit def indexedIndexable[I]: Indexable[I, Indexed[I, ?, ?]] = | |
new Indexable[I, Indexed[I, ?, ?]] { | |
def index[A, B](ix: Indexed[I, A, B])(i: I)(a: A) = ix.runIndexed(i)(a) | |
} | |
def index[I, P[_, _], A, B]( | |
pab: P[A, B])( | |
i: I)( | |
a: A)(implicit | |
I: Indexable[I, P]): B = | |
I.index(pab)(i)(a) | |
} |
Hacking on the AVE:
def plist[A, B] = new IPTraversal[Int, List[A], List[B], A, B] {
def modifyF[
F[_]: Applicative,
P[_, _]: Indexable[Int, ?[_, _]]](
f: P[A, F[B]])(s: List[A]): F[List[B]] =
{
val app = Applicative[F]
def loop(i: Int, l: List[A], acc: F[List[B]]): F[List[B]] =
l match {
case Nil => acc
case x::xs =>
loop(i+1, xs,
app.apply2(acc, app.map(indexHelper(f)(i)(x))(List(_))){_ ++ _})
}
loop(1, s, Applicative[F].point(List()))
}
}
Running it:
plist[String, String].getAll(List("hi", "traversal")) // List((1,hi), (2,traversal))
plist[String, String].modify(i => s => if (i % 2 ==0) s.toUpperCase else s)(List("hi", "traversal")) // List("hi", "TRAVERSAL")
Thanks for all!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Using indexed traversal interface: