【问题标题】:Common practice for higher-order-polymorphism in scalascala中高阶多态性的常见做法
【发布时间】:2011-02-04 10:00:41
【问题描述】:

我试图通过实现一个描述 monad 的非常基本的接口来掌握 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 类型构造函数的基本概念我似乎不了解。

问候, 雷乔

【问题讨论】:

  • 谢谢,该链接看起来很有趣,但并没有真正回答我的问题。我不想知道任何关于单子的事情,我的问题是关于类型构造函数的多态性。尽管如此,它看起来像一本好书。 :)

标签: scala types polymorphism monads higher-kinded-types


【解决方案1】:

不确定什么是最好的解决方案,但在您的代码中对 pure 的定义:

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

Container[A](a) 应该做什么?到目前为止,您已经将 Container 定义为泛型类型 XXX,并且您没有任何关于如何构建新对象的信息。您需要将“builder”对象作为隐式参数传递。 看看集合库是如何在 Scala 2.8 或 Scalaz 中的 Monad 定义实现的

【讨论】:

    【解决方案2】:

    如果您将Monad 类的定义更改为以下内容

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

    Container[_] 的语法是 Scala 中如何表达更高种类的。 A &lt;% Container[A] 是一个“视图绑定”,表示A 可以隐式转换为Container[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
    

    【讨论】:

    【解决方案3】:

    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[_] 进行参数化。方括号内的下划线表示Mkind (* -&gt; *) 的类型构造函数(即M 采用某种类型A 来构造类型M[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)
    }
    

    此定义使用名称参数来实现惰性语义。

    Scalaz 库提供了 Monad 和其他有用的高级类型类以及标准 Java/Scala 库的大量实例。

    【讨论】:

    • 太棒了,我的脑袋爆炸了,但这正是我一直在寻找的。谢谢:)
    猜你喜欢
    • 2021-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 1970-01-01
    • 2021-02-01
    • 2015-04-14
    相关资源
    最近更新 更多