All Downloads are FREE. Search and download functionalities are using the official Maven repository.

doodle.image.examples.ParticleSystem.scala Maven / Gradle / Ivy

There is a newer version: 0.27.0
Show newest version
/*
 * Copyright 2015 Creative Scala
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package doodle
package image
package examples

// import doodle.core._
//import doodle.syntax.all._
// import doodle.random._
import cats.Monad
import cats.Monoid
import cats.data.Kleisli
import cats.data.WriterT
import cats.implicits.*

object ParticleSystem {

  def walk[F[_]: Monad, A](
      steps: Int,
      step: Kleisli[F, A, A]
  ): Kleisli[F, A, A] = {
    Kleisli(a => {
      def loop(count: Int, fa: F[A]): F[A] =
        count match {
          case 0 => fa
          case n => loop(n - 1, fa flatMap step.run)
        }

      loop(steps - 1, step(a))
    })
  }

  def trace[F[_]: Monad, A, B: Monoid](steps: Int, step: Kleisli[F, A, A])(
      f: A => B
  ): Kleisli[F, A, B] = {
    type Result[T] = WriterT[F, B, T]

    walk[Result, A](
      steps,
      Kleisli(a => WriterT.putT(step(a))(f(a)))
    ).mapF(fa => fa.written)
  }

  def particles[F[_]: Monad, A, B: Monoid](
      count: Int,
      initial: F[A],
      walk: Kleisli[F, A, B]
  ) = {
    def loop(count: Int, fb: F[B]): F[B] = {
      count match {
        case 0 => fb
        case n => loop(n - 1, ((initial flatMap walk.run), fb).mapN(_ |+| _))
      }
    }

    loop(count, Monad[F].pure(Monoid[B].empty))
  }

  implicit object imageOnMonoid extends Monoid[Image] {
    val empty: Image = Image.empty
    def combine(x: Image, y: Image): Image = x on y
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy