scala - 如何将函数的返回类型指定为(任意)monad?

标签 scala monads scalaz monad-transformers

简而言之,我想声明这样的特征:

trait Test {
    def test(amount: Int): A[Int] // where A must be a Monad
}

这样我就可以在不知道 A 是什么 monad 的情况下使用它是,例如:

class Usecase {
    def someFun(t: Test) = for { i <- t.test(3) } yield i+1
}

更多详细信息...

本质上,我想做这样的事情:

class MonadResultA extends SomeUnknownType {
    // the base function
    def test(s: String): Option[Int] = Some(3)
}

class MonadResultB(a: MonadResultA) extends SomeUnknownType {
    // added a layer of Writer on top of base function
    def test(s: String): WriterT[Option, String, Int] = WriterT.put(a.test(s))("the log")
}

class Process {
    def work(x: SomeUnknownType) {
        for {
            i <- x.test("key")
        } yield i+1
    }
}

我希望能够传递 MonadResultA 的任何实例 MonadResultB无需对函数 work 进行任何更改.
缺少的部分是 SomeUnknowType ,我想应该有 test像下面这样制作work函数编译。

trait SomeUnknowType {
    def test(s: String): T[Int] // where T must be some Monad
}

正如我所说,我仍在学习这个 monad 的东西...如果您发现我的代码不是正确的方法,我们非常欢迎您指出它出来~

非常感谢~~

最佳答案

假设您有一个名为 Monad 的类型类,您可以直接编写

def test[A:Monad](amount: Int): A[Int]

调用测试时,编译器将要求作用域中存在隐式类型 Monad[A]

编辑: 我仍然不确定您在寻找什么,但是您可以将 monad 值及其相应的类型类打包在这样的特征中:

//trait that holds value and monad
trait ValueWithMonad[E] {
  type A[+E]
  type M <: Monad[A]
  val v:A[E]
  val m:M
}

object M {

  //example implementation of test method
  def test(amount:Int):ValueWithMonad[Int] = new ValueWithMonad[Int] {
    type A[+E] = Option[E]
    type M = Monad[Option]
    override val v = Option(amount)
    override val m = OptionMonad
  }

  //test can now be used like this
  def t {
    val vwm = test(1)
    vwm.m.bind(vwm.v, (x:Int) => {
      println(x)
      vwm.m.ret(x)
    })
  }
}

trait Monad[A[_]] {
  def bind[E,E2](m:A[E], f:E=>A[E2]):A[E2]
  def ret[E](e:E):A[E]
}

object OptionMonad extends Monad[Option] {
  override def bind[E,E2](m:Option[E], f:E=>Option[E2]) = m.flatMap(f)
  override def ret[E](e:E) = Some(e)
}

关于scala - 如何将函数的返回类型指定为(任意)monad?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11883581/

相关文章:

haskell - 结合仿函数和单子(monad)

scala - 为了理解 future 和两者

scala - 当返回类型为 Option[Error] 时处理快速失败失败

scala - 将 Option[Validation[E, A]] 转换为 Validation[E, Option[A]]

scala - 在样式中使用Scala隐式编码

scala - 类型构造函数是单子(monad)还是有单子(monad)?

scala - Spark数据帧将整数转换为时间戳并找到日期差异

logging - 如何登录 Haskell?

Scala 模式匹配在 2.10 中的递归类型上失败

scala - 如何为泛型类型编写 scalaz.IsEmpty 参数