Translation of this monadic counter from Haskell to Scala

I have defined a monadic counter in Haskell , which I am trying to translate into Scala, so far not depressing. The problem in a nutshell is the implementation of the counter as a state monad, which reads the constant increment of the counter from the environment and records the history of the counter (its sequence of values).

My friend improved my solution and came up with this simple solution:

newtype Counter = Counter Int deriving (Eq)

instance Show Counter where
  show (Counter i) = show i

incWith :: MonadState Counter m => Int -> m ()
incWith n = let incCounter n' (Counter i) = Counter $ i + n'
            in modify (incCounter n)

inc :: (MonadReader Int m, MonadState Counter m, MonadWriter [Counter] m) => m ()
inc = ask >>= incWith >> get >>= tell . (:[])

compute :: (MonadReader Int m, MonadState Counter m, MonadWriter [Counter] m) => m ()
compute =
  local (const 3) $ do
    inc
    inc
    inc
    local (const 5) $ do
      inc
      inc

I tried without success to encode this in Scala + (Cats | ScalaZ). The latest stable version of Cats has no method liftfor WriterT. And with ReaderWriterStatein ScalazI could not understand after a couple of hours how to use the method local. And this is just the beginning ...

Haskell ? ( , ).

:

, , Haskell Scala + FP (Cats, Scalaz). Haskell - , Scala IntelliJ, GitHub StackOverflow . , , .

+4
1

, :

  import scalaz._
  import Scalaz._
  val SM = ReaderWriterState.rwstMonad[Id, Int, List[String], Counter]

  case class Counter(value: Int)

  def incWith(n: Int): State[Counter, Unit] = for {
    v ← get[Counter]
    _ ← put(Counter(v.value + n))
  } yield ()

  def inc: IRWS[Int, List[String], Counter, Counter, Unit] = for {
    v ← SM.ask
    c ← SM.get
    _ ← SM.tell(List(s"Incrementing $c by $v "))
    _ ← SM.modify(counter ⇒ Counter(counter.value + v))
  } yield ()

  def compute: IRWS[Int, List[String], Counter, Counter, Unit] = {
    for {
      _ <- SM.local[Unit](i ⇒ 3)(for {
        _ ← inc
        _ ← inc
        _ ← inc
      } yield ())
      _ <- SM.local[Unit](i ⇒ 5)(for {
        _ ← inc
        _ ← inc
        _ ← inc
      } yield ())
    } yield ()
  }

  println(incWith(5)(Counter(0)))
  println(inc.run(4, Counter(0)))
  println(compute.run(0, Counter(0)))
+2

Source: https://habr.com/ru/post/1653513/


All Articles