2019-01-27: てらちー氏・4869と会った
やったこと
diaryの芝に凡例を追加した
キャッシュ周りをいい感じにできたので、芝に凡例を追加してみた。
ぶっちゃけ有っても無くてもどうでもいいのだけど。
てらちー氏、4869と会った
てらちー氏と話したいことはいくつかあったのだけど、忙しそうなので残念。あとでどうにかする。
思ったより難しそうなのでどこかで時間を取らないとマズい。無理。
上野のHUBとか赤からとか行った。そろそろ赤からに飽きる。悪くないけど。
思うこと
LeanPropsのTiers
はMonadにならないのだろうか
諦めきれず未だに考察してる。
まず分かったこととしていわゆるListT
を次のように定義した場合、F
がMonadでもListT[F, ?]
がMonadになるとは限らないらしい。
final case class ListT[F[_], A](value: F[List[A]]) extends AnyVal {
// ...
}
この場合でListT[F, ?]
がMonadになるのは、F
がcommutativeな場合に限るらしい。
そこで、このようにListT
を定義すると、Functor
であるF
に対してListT
がMonadになるらしい。
final case class ListT[F[_], A](value: F[Option[Either[ListT[F, A], (A, ListT[F, A])]]]) {
def map[B](f: A => B)(implicit F: Functor[F]): ListT[F, B] = ListT(F.map(this.value) {
case None => None
case Some(Left(l)) => Some(Left(l.map(f)))
case Some(Right((a, l))) => Some(Right((f(a), l.map(f))))
})
def flatMap[B](f: A => ListT[F, B])(implicit F: Functor[F]): ListT[F, B] = ListT(F.map(this.value) {
case None => None
case Some(Left(l)) => Some(Left(l.flatMap(f)))
case Some(Right((a, l))) => Some(Left(f(a) ++ l.flatMap(f)))
})
def ++(that: => ListT[F, A])(implicit F: Functor[F]): ListT[F, A] = ListT(F.map(this.value) {
case None => Some(Left(that))
case Some(Left(l)) => Some(Left(l ++ that))
case Some(Right((a, l))) => Some(Right(a, l ++ that))
})
def toList(implicit F: Monad[F]): F[List[A]] = {
def loop(l: ListT[F, A], as: List[A]): F[List[A]] =
F.flatMap(l.value) {
case None => F.point(as)
case Some(Left(l2)) => loop(l2, as)
case Some(Right((a, l2))) => loop(l2, a +: as)
}
F.map(loop(this, List.empty))(_.reverse)
}
}
object ListT {
def empty[F[_], A](implicit F: Applicative[F]): ListT[F, A] = ListT[F, A](F.point(None))
}
このListT
にStream
を入れると、見かけ上は少なくともTiers
と同じ型になるな、と思ったのだけど、そこからがよく分からない、というか上手くいかない。
あとこの実験用に定義したMonadとか。ひさしぶりにこんなん書いた。
import scala.language.higherKinds
trait Functor[F[_]] {
def map[A, B](fa: F[A])(f: A => B): F[B]
}
object Functor {
implicit val ListFunctor: Functor[List] = new Functor[List] {
def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
}
}
trait Applicative[F[_]] extends Functor[F] {
def point[A](a: A): F[A]
def ap[A, B](ff: F[A => B])(fa: F[A]): F[B]
override def map[A, B](fa: F[A])(f: A => B): F[B] = ap(point(f))(fa)
}
object Applicative {
implicit val ListApplicative: Applicative[List] = new Applicative[List] {
override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
def point[A](a: A): List[A] = List(a)
def ap[A, B](ff: List[A => B])(fa: List[A]): List[B] = for {
f <- ff
a <- fa
} yield f(a)
}
}
trait Monad[F[_]] extends Applicative[F] {
def flatMap[A, B](fa: F[A])(f: A => F[B]): F[B]
override def ap[A, B](ff: F[A => B])(fa: F[A]): F[B] = flatMap(ff)(f => map(fa)(f))
}
object Monad {
implicit val ListMonad: Monad[List] = new Monad[List] {
override def map[A, B](fa: List[A])(f: A => B): List[B] = fa.map(f)
override def ap[A, B](ff: List[A => B])(fa: List[A]): List[B] = for {
f <- ff
a <- fa
} yield f(a)
def point[A](a: A): List[A] = List(a)
def flatMap[A, B](fa: List[A])(f: A => List[B]): List[B] = fa.flatMap(f)
}
}