【问题标题】:Making the type signature independent of a specific monad transformer stack (Scala)使类型签名独立于特定的 monad 转换器堆栈 (Scala)
【发布时间】:2014-03-25 13:28:12
【问题描述】:

我通过将 Haskell 函数转换为 Scala 来学习 Scala。我有一个包含 StateMonad 的单子变压器堆栈

type TI a = ... 

使用这个 monad 转换器堆栈的一个函数是:

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

由于这个函数只依赖于 State monad,我也可以将类型更改为:

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

这如何转化为 Scala?在 Scala 中,我使用组成状态和身份单子的单子转换器堆栈:

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

Scala 中的新函数如下所示:

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

如何在 Scala 中重写类型签名,使其仅依赖于 State monad 而不是整个 monad 转换器堆栈?

【问题讨论】:

    标签: scala haskell monads


    【解决方案1】:

    Scalaz 还提供了一个MonadState 类型类,尽管 Scala 类型推断的局限性意味着它不那么优雅。例如,您可以编写以下内容:

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

    然后例如以下内容:

    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
    

    注意MonadState 的第一个类型参数需要对状态和值都有孔,所以如果你想使用这种方法,你需要调整你的TI——fresh[TI] 不会按原样工作。

    【讨论】:

      猜你喜欢
      • 2011-01-06
      • 1970-01-01
      • 2014-05-03
      • 2017-01-09
      • 2011-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多