在斯卡拉堆积StateT

编程入门 行业动态 更新时间:2024-10-11 19:22:18
本文介绍了在斯卡拉堆积StateT的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我试图通过从Dan Piponi的本教程中移植一些示例来了解Scala中的Monad Transformers: blog.sigfpe/2006/05/grok-haskell-monad-transformers.html

我做了几个简单的:

import Control.Monad.State import Control.Monad.Identity test1 = do a < - get modify(+1)b < - get return(a, b) test2 = do a < - get modify(++1)b < - get return(a,b ) go1 = evalState test1 0 go2 = evalState test20

变成:

import scalaz._,Scalaz._ val test1 = for {a < - get [Int] _< - modify [Int](1+)b < - get } yield( a,b) val test2 = for {a < - get [String] _< - modify [String](_ +1)b< - get }收益率(a,b) val go1 = test1.eval(0) val go2 = test2.eval(0) 但是我怎么能把这个下一个例子移植到Scala?

test3 = do modify(+ 1) lift $ modify(++1)a < - get b< - lift get return(a,b) go3 = runIdentity $ evalStateT(evalStateT test3 0)0

我使用scalaz 7.1.0-M6得到了这么多:

type SST [F [_],A] = StateT [F,String,A] type IST [F [_],A] = StateT [F ,Int,A] val p1:StateT [Id,Int,Unit] = modify [Int](1+) val p2:StateT [Id,String,Unit] =修改[String](_ +1) val p3:StateT [({type l [a] = StateT [Id,String,a]})#l,Int,Unit] = p2.liftM [IST ]

但这还没有结束,甚至可能会倒退。当然我可以这样做: pre $ code $> import scalaz.Lens._ val test3 = for { _< - firstLens [Int,String] lifts(modify(1+)) _< - secondLens [Int,String ]升降机(修改(_ +1))a < - firstLens [Int,String]升降机获得b< - secondLens [Int,String]升降机获得} ,b) val go3 = test3.eval(0,0)

预先感谢!

解决方案

问题在于,通常导入的修改来自州,并不会帮助你 StateT 。

从Haskell类型签名开始:

s(tm),MonadTrans t, Num s)=> tm(s,[Char])

您应该可以将其转换成类似这:

import scalaz._,Scalaz._ def test3 [M [_]: Monad](隐式 inner:MonadState [({type T [s,a] = StateT [M,s,a]})#T,String], outer:MonadState [ ({ type T [s,a] = StateT [({type L [y] = StateT [M,String,y]})#L,s,a] })#T, Int mt:MonadTrans [({type L [f [_],a] = StateT [f,Int,a]})#L] ) = for { _< - outer.modify(_ + 1) _< - mt.liftMU(inner.modify(_ +1))a < - outer .get b< - mt.liftMU(inner.get)} yield(a,b)

这是可怕的,但它是对Haskell的一个相当直接的重新说明。由于某种原因,编译器似乎没有找到 outer 实例,所以你必须帮助它:

def test3 [M [_]:Monad](隐式 inner:MonadState [({type T [s,a] = StateT [M,s,a ]})#T,String], mt:MonadTrans [({type L [f [_],a] = StateT [f,Int,a]})#L] )= { val outer = StateT.stateTMonadState [Int,({type L [y] = StateT [M,String,y]})#L] for { _< - outer.modify(_ + 1) _< - mt.liftMU(inner.modify(_ +1))a < - outer.get b < - mt.liftMU(inner.get)} yield(a,b)}

现在您可以编写以下内容,例如:

scala> test3 [Id] .eval(0).eval(0) res0:(Int,String)=(1,01)

与Haskell示例完全一样。 脚注

如果您满意于将 Id 作为内部状态转换器的monad(如您的评论所示),那么可以清理一下:

def test3 = { val mt = MonadTrans [({type L [f [_],a] = StateT [f,Int, a]})#L] val outer = StateT.stateTMonadState [Int,({type L [y] = State [String,y]})#L] for { _ < - outer.modify(_ + 1) _< - mt.liftMU(modify [String](_ +1))a < - outer.get b< ; - mt.liftMU(get [String])} yield(a,b)}

这不是一般的,但它可能适用于您。

I'm trying to understand Monad Transformers in Scala by porting some examples from this tutorial by Dan Piponi: blog.sigfpe/2006/05/grok-haskell-monad-transformers.html

I did a couple of easy ones:

import Control.Monad.State import Control.Monad.Identity test1 = do a <- get modify (+1) b <- get return (a,b) test2 = do a <- get modify (++"1") b <- get return (a,b) go1 = evalState test1 0 go2 = evalState test2 "0"

becomes:

import scalaz._, Scalaz._ val test1 = for { a <- get[Int] _ <- modify[Int](1+) b <- get } yield (a,b) val test2 = for { a <- get[String] _ <- modify[String](_ + "1") b <- get } yield (a,b) val go1 = test1.eval(0) val go2 = test2.eval("0")

But how the heck can I port this next example to Scala?

test3 = do modify (+ 1) lift $ modify (++ "1") a <- get b <- lift get return (a,b) go3 = runIdentity $ evalStateT (evalStateT test3 0) "0"

I've gotten this far using scalaz 7.1.0-M6:

type SST[F[_],A] = StateT[F,String,A] type IST[F[_],A] = StateT[F,Int,A] val p1: StateT[Id,Int,Unit] = modify[Int](1+) val p2: StateT[Id,String,Unit] = modify[String](_ + "1") val p3: StateT[({type l[a]=StateT[Id,String,a]})#l,Int,Unit] = p2.liftM[IST]

but that's not even close yet, and may even be backwards for all I can tell.

Of course I can do this:

import scalaz.Lens._ val test3 = for { _ <- firstLens[Int,String] lifts (modify (1+)) _ <- secondLens[Int,String] lifts (modify (_ + "1")) a <- firstLens[Int,String] lifts get b <- secondLens[Int,String] lifts get } yield (a,b) val go3 = test3.eval(0,"0")

but then I'm not using stacked StateT at all, so it doesn't answer the question.

Thanks in advance!

解决方案

The problem is that the modify you get with the usual imports is from State, and isn't going to help you with StateT.

It's a good idea to start with the Haskell type signature:

test3 :: (MonadState [Char] m, MonadState s (t m), MonadTrans t, Num s) => t m (s, [Char])

Which you should be able to translate into something like this:

import scalaz._, Scalaz._ def test3[M[_]: Monad](implicit inner: MonadState[({ type T[s, a] = StateT[M, s, a] })#T, String], outer: MonadState[ ({ type T[s, a] = StateT[({ type L[y] = StateT[M, String, y] })#L, s, a ] })#T, Int ], mt: MonadTrans[({ type L[f[_], a] = StateT[f, Int, a] })#L] ) = for { _ <- outer.modify(_ + 1) _ <- mt.liftMU(inner.modify(_ + "1")) a <- outer.get b <- mt.liftMU(inner.get) } yield (a, b)

It's hideous, but it's a fairly straightforward rewording of the Haskell. For some reason the compiler doesn't seem to find the outer instance, though, so you have to help it a little:

def test3[M[_]: Monad](implicit inner: MonadState[({ type T[s, a] = StateT[M, s, a] })#T, String], mt: MonadTrans[({ type L[f[_], a] = StateT[f, Int, a] })#L] ) = { val outer = StateT.stateTMonadState[Int, ({ type L[y] = StateT[M, String, y] })#L] for { _ <- outer.modify(_ + 1) _ <- mt.liftMU(inner.modify(_ + "1")) a <- outer.get b <- mt.liftMU(inner.get) } yield (a, b) }

Now you can write the following, for example:

scala> test3[Id].eval(0).eval("0") res0: (Int, String) = (1,01)

Exactly as in the Haskell example.

Footnote

You can clean this up a bit if you're happy with committing to Id as the monad of the inner state transformer (as your comment suggests):

def test3 = { val mt = MonadTrans[({ type L[f[_], a] = StateT[f, Int, a] })#L] val outer = StateT.stateTMonadState[Int, ({ type L[y] = State[String, y] })#L] for { _ <- outer.modify(_ + 1) _ <- mt.liftMU(modify[String](_ + "1")) a <- outer.get b <- mt.liftMU(get[String]) } yield (a, b) }

It's a little less generic, but it may work for you.

更多推荐

在斯卡拉堆积StateT

本文发布于:2023-07-15 13:18:31,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1111439.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:斯卡   StateT

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!