7

モナドを記述する非常に基本的なインターフェースを実装することで、scalaの高階ポリモフィズムを把握しようとしていますが、実際には理解できない問題に遭遇します。

私はC++で同じことを実装し、コードは次のようになります。

#include <iostream>

template <typename T>
class Value {
private:
  T value;
public:
  Value(const T& t) {
    this->value = t;
  }

  T get() {
    return this->value;
  }
};

template < template <typename> class Container >
class Monad {
public:
  template <typename A> Container<A> pure(const A& a); 
};

template <template <typename> class Container>
  template <typename A>
Container<A> Monad<Container>::pure(const A& a) {
  return Container<A>(a);
}

int main() {
  Monad<Value> m;
  std::cout << m.pure(1).get() << std::endl;
  return 0;
}

Scalaで同じことをしようとすると、失敗します。

class Value[T](val value: T)

class Monad[Container[T]] {
  def pure[A](a: A): Container[A] =
    Container[A](a)
}

object Main {
  def main(args: Array[String]): Unit = { 
    val m = new Monad[Value]
    m.pure(1)
  }
}

コンパイラは次のことについて文句を言います。

[raichoo@lain:Scala]:434> scalac highorder.scala
highorder.scala:5: error: not found: value Container
    Container[A](a)
    ^
one error found

私はここで何が間違っているのですか?私がscalaタイプコンストラクターについて理解していないように見える基本的な概念があるようです。

よろしく、raichoo

4

3 に答える 3

16

ScalaのMonad特性は次のように宣言されます。

trait Monad[M[_]] {
  def pure[A](a: => A): M[A]
  def bind[A,B](a: M[A], f: A => M[B]): M[B]
}

型コンストラクターでパラメーター化されていることに注意してくださいM[_]。括弧で囲まれたアンダースコアは、が種類の型コンストラクターであることを示しますMつまり、型を構築するために何らかの型を取ります)。IDモナドインスタンスは次のように記述されます。 (* -> *)MAM[A]

class Value[A](a: => A) { lazy val value = a }

implicit val identityMonad = new Monad[Value] {
  def pure[A](a: => A) = new Value(a)
  def bind[A,B](a: Value[A], f: A => Value[B]) = new Value(f(a.value).value)
}

この定義では、名前によるパラメーターを使用して、遅延セマンティクスを実現します。

モナドやその他の便利な高種類の型クラスは、標準のJava/Scalaライブラリの多くのインスタンスとともにScalazライブラリによって提供されます。

于 2010-04-05T16:18:12.297 に答える
5

Monadクラスの定義を次のように変更した場合

class Monad[Container[_]] {        
  def pure[A <% Container[A]](a: A): Container[A] = a
}

構文Container[_]は、Scalaでより高い種類がどのように表現されるかです。は、暗黙的にに変換可能A <% Container[A]であることを表す「ビューバウンド」です。メソッドの本体は、この暗黙の変換を使用します。このクラスを使用するには、(あなたの例では)次のスコープで暗黙的な変換を行う必要がありますAContainer[A]IntValue[Int]

implicit def toValue[T](t:T) = new Value(t)

その後、次のことができます

scala> val m = new Monad[Value]                     
m: Monad[Value] = Monad@781fb069

scala> m.pure(1).value         
res3: Int = 1
于 2010-04-05T14:53:00.450 に答える
3

何が最善の解決策になるかはわかりませんが、コードの純粋な定義では次のようになります。

class Monad[Container[T]] {
  def pure[A](a: A): Container[A] = Container[A](a)
}

Container[A](a)をすべきですか?これまでのところ、Containerをジェネリック型XXXとして定義しており、新しいオブジェクトを作成する方法についての情報はありません。「ビルダー」オブジェクトを暗黙のパラメーターとして渡す必要があります。コレクションライブラリがScala2.8またはScalazのモナド定義でどのように実装されているかを見てください

于 2010-04-05T14:44:53.110 に答える