简体   繁体   English

使类型签名独立于特定的monad变换器堆栈(Scala)

[英]Making the type signature independent of a specific monad transformer stack (Scala)

I'm learning Scala by translating a Haskell function to Scala. 我正在通过将Haskell函数转换为Scala来学习Scala。 I have a monad transformer stack containing the StateMonad 我有一个包含StateMonad的monad变换器堆栈

type TI a = ... 

One function using this monad transformer stack is: 使用此monad变换器堆栈的一个功能是:

fresh :: TI Int
fresh = do n <- get
           put (n + 1)
           return n

Since this function only depends on the State monad I may also change the type to: 由于此函数仅依赖于状态monad,因此我也可以将类型更改为:

fresh :: (MonadState Int m) => m Int

How does this translate to Scala? 这如何转化为Scala? In Scala, I use a monad transformer stack composing the state and the identity monad: 在Scala中,我使用构成状态和身份monad的monad变换器堆栈:

type TI[A] = StateT[Id, scala.Int, A]

The fresh function in Scala looks like this: Scala中的新功能如下所示:

def fresh:TI[Ty] = for {
  counter <- get[scala.Int]
  _ <- put[scala.Int] (counter + 1)
} yield {
  TyVar(counter)
}

How do I rewrite the type signature in Scala in such a way that in only depends on the State monad and not on the whole monad transformer stack? 如何以这样的方式重写Scala中的类型签名:仅依赖于State monad而不是整个monad转换器堆栈?

Scalaz also provides a MonadState type class, although the limitations of Scala's type inference means it's much less elegant. Scalaz还提供了一个MonadState类型类,虽然Scala类型推断的局限性意味着它不那么优雅。 You could write the following, for example: 您可以编写以下内容,例如:

import scalaz._, Scalaz._

def fresh[F[_, _]](implicit m: MonadState[F, Int]): F[Int, Int] = for {
  counter <- m.get
  _       <- m.put(counter + 1)
} yield counter

And then for example the following: 然后举例如下:

scala> fresh[State]
res6: scalaz.State[Int,Int] = scalaz.IndexedStateT$$anon$10@6517b62

scala> type OptionState[s, a] = StateT[Option, s, a]
defined type alias OptionState

scala> fresh[OptionState]
res7: OptionState[Int,Int] = scalaz.IndexedStateT$$anon$10@43740ba6

Note that the first type parameter for MonadState needs to have holes for both the state and the value, so you'll need to adjust your TI if you want to use this approach— fresh[TI] won't work as is. 请注意, MonadState的第一个类型参数需要为状态和值都设置漏洞,因此如果要使用此方法,则需要调整TI fresh[TI]将无法正常工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM