[英]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缺乏WriterT
的lift
方法。 使用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.