Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何将'scalaz.FreeT'运行到非堆栈安全monad中?_Scala_Scalaz - Fatal编程技术网

如何将'scalaz.FreeT'运行到非堆栈安全monad中?

如何将'scalaz.FreeT'运行到非堆栈安全monad中?,scala,scalaz,Scala,Scalaz,我正试着把我的头绕在免费的单子(和变形金刚)上。我已经能够使用scalaz.FreeT和一个解释器构建我自己的免费monad,该解释器将它运行到一个看似任意的monad中,首先天真地提升到目标monad中,然后运行免费monad,如下所示: import scalaz._ import Scalaz._ type MyCoolMonad[A] = FreeT[SomeFunctor, Id, A] type ResultMonad[A] = ??? // for example Id[A] d

我正试着把我的头绕在免费的单子(和变形金刚)上。我已经能够使用
scalaz.FreeT
和一个解释器构建我自己的免费monad,该解释器将它运行到一个看似任意的monad中,首先天真地提升到目标monad中,然后运行免费monad,如下所示:

import scalaz._
import Scalaz._

type MyCoolMonad[A] = FreeT[SomeFunctor, Id, A]
type ResultMonad[A] = ??? // for example Id[A]
def id2monadNT[R[_]: Monad]: (id ~> R) = { 
  override def apply[A](fa: A) = fa.point[R]
} // for hoisting
val myInterpreter = new (SomeFunctor ~> ResultMonad) {
  override def apply[A](fa: SomeFuntor[A]) = {...} // the meat is here
}

def runCoolMonad[A](m: MyCoolMonad[A]) = 
  m.hoistN(id2monadNT[R]).runM(myInterpreter.apply)
因此,第一个也是不太重要的问题是,我是否必须提升,以便将自由单子运行到其他任意单子中?似乎有点过分了

主要过程是:
.runM
需要
ResultMonad
提供一个
BindRec
实例,证明可以在恒定的堆栈空间中绑定
ResultMonad
。我希望有一个解释器运行我的免费monad,结果是使用
scala.concurrent.Future
,这不是堆栈安全的。有办法吗?我知道我放弃了某种保证,但作为开发人员,我有信心
Future.flatMap
堆栈不会太深而引起任何麻烦(我们使用的是纯
Futures
,到处都没有免费的monad,而且工作正常)

我正在使用Scalaz 7.2.1,据我所知,它是最新的


旁注:我知道存在
scalaz.concurrent.Task
,我仍然想知道如何将free monad解释为
scala.concurrent.Future

来回答你的第一个问题:如果你只有
FreeT[SomeFunctor,Id,A]
,它相当于
free[SomeFunctor,A]
。然后给定
SomeFunctor~>Future
,您可以将
Free[SomeFunctor,A]
解释为
Future[A]
。也就是说,无需使用
FreeT
和吊装。另外,
Free
允许您对任何单子进行解释

FreeT
是对
scalaz
的最新添加。虽然
Free
最初设计用于解释任何monad,而堆栈安全版本的操作只是后来添加的,
FreeT
从一开始就只支持堆栈安全monad

如果您仍然希望将
FreeT
scala.concurrent.Future
一起使用,只需提供一个
BindRec
实例即可

implicit def futureBindRec: BindRec[Future] = new BindRec[Future] {
  def tailrecM[A, B](f: A => Future[A \/ B])(a: A): Future[B] =
    f(a) flatMap {
      case -\/(a1) => tailrecM(f)(a1)
      case \/-(b) => Future(b)
    }
  def map...
  def bind...
}

如果
Future#flatMap(f)
从不急切地调用
f
(在一个完整的
Future
上可能会这样做,但我对它还不太熟悉,所以我宁愿构建monad转换器,而不是简单的monad,因为它具有可组合性。关于提供
BindRec[Future]
实例的观点很好——我只是盲目地认为这是不可能的,我将检查这是否有效。我最初的问题已经解决了,但是对于如何在真正非堆栈安全的monad中解释
FreeT
,您还有其他见解吗?
BindRec
的上述实现几乎可以一字不差地适用于任何monad。它只是有可能在某些情况下溢出堆栈。另一种迂回的方法是将
FreeT[S,M,A]
提升到
FreeT[S,Free[M,A]
,将其解释为
Free[M,A]
(这是堆栈安全的),然后将其解释为非堆栈安全的monad
M
。当然
FreeT
可以通过解释为任何monad的方法进行扩展。我不相信它会非常有用。