2

要するに、次のような特性を宣言したいと思います。

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

モナドが何であるかを知らなくても使用できるようにA、次のようにします。

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 または のインスタンスを渡すことができるようにしたかったのです。 欠けている部分は、関数をコンパイルするために以下のようにする必要があると思います。MonadResultBwork
SomeUnknowTypetestwork

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

私が言ったように、私はまだこのモナドのことを学んでいます... 私のコードがそれを行う正しい方法ではないことがわかったら、それを指摘することは大歓迎です~

どうもありがとう~~

4

1 に答える 1

4

と呼ばれる型クラスがあると仮定すると、Monadただ書くことができます

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

Monad[A]コンパイラは、テストが呼び出されるときにスコープ内に暗黙の型があることを要求します。

EDIT: あなたが探しているものはまだわかりませんが、モナド値を対応する型クラスと一緒にトレイトにまとめることができます:

//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)
}
于 2012-08-09T12:50:30.590 に答える