簡體   English   中英

將這個monadic計數器從Haskell翻譯成Scala

[英]Translating this monadic counter from Haskell to Scala

在Haskell中定義了一個monadic計數器 ,我試圖將其轉換為Scala,到目前為止失敗了。 簡而言之,問題是將計數器實現為狀態monad,它從環境中讀取計數器增量常量,並記錄計數器的歷史記錄(其值序列)。

我的一個朋友改進了我的解決方案,並提出了這個簡單的解決方案:

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

我試過沒有成功將此代碼為斯卡拉+(貓| ScalaZ)。 最新穩定版的Cats缺乏WriterTlift方法。 使用Scalaz ReaderWriterState ,我無法在幾個小時內弄清楚如何使用local方法。 那只是開始......

如何以簡單而優雅的方式翻譯這個Haskell解決方案? (在語言允許的范圍內)。

邊注:

我還在試圖找出為什么我需要花費這么多時間將簡單的解決方案從Haskell轉換為Scala + FP庫(Cats,Scalaz)。 在Haskell中查找每個類型類的實例和可用函數是輕而易舉的,在Scala中使用IntelliJ,GitHub和StackOverflow這需要幾天時間。 所以我想知道我做錯了什么,我怎么能改善這種情況呢。

如果我理解你的意圖是正確的,那么這就轉化為非常簡單易懂的代碼:

  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)))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM