17

我正在学习函数式编程风格。在Don't Fear the Monads中,Brian Beckman 对 Monad 做了精彩的介绍。他提到 Monad 是关于函数的组合以解决复杂性。

Monad 包含unit将 T 型转换为放大型 M(T) 的功能;和一个 Bind 函数,给定从 T 到 M(U) 的函数,将类型 M(T) 转换为另一种类型 M(U)。(U可以是T,但不一定)。

据我了解,实现 monad 的语言应该进行静态类型检查。否则编译时找不到类型错误,“复杂度”不受控制。我的理解正确吗?

4

4 回答 4

27

在动态类型语言中有很多 monad 的实现:

一般来说,Church-Turing-Thesis 告诉我们,可以用一种语言完成的所有事情也可以用其他所有语言完成。

从上面选择的示例中您可能可以看出,我(主要)是一名 Ruby 程序员。所以,开个玩笑,我拿了上面的一个例子,用一种我完全不知道的语言重新实现了它,这通常被认为是一种不是很强大的语言,而且它似乎是唯一的编程语言在我无法找到 Monad 教程的星球上。我可以向您介绍... PHP 中的 Identity Monad:

<?php
class Identity {
  protected $val;
  public function __construct($val) { $this->val = $val; }
  public static function m_return($a) { return new Identity($a); }
  public static function m_bind($id_a, $f) { return $f($id_a->val); }
}

var_dump(Identity::m_bind(
  Identity::m_return(1), function ($x) {
    return Identity::m_return($x+1);
  }
));
?>

没有静态类型,没有泛型,不需要闭包。

现在,如果你真的想静态检查 monad,那么你需要一个静态类型系统。但这或多或少是一个重言式:如果你想静态检查类型,你需要一个静态类型检查器。呃。

关于你的问题:

据我了解,实现 monad 的语言应该进行静态类型检查。否则编译时找不到类型错误,“复杂度”不受控制。我的理解正确吗?

你是对的,但这与单子无关。这只是一般的静态类型检查,同样适用于数组、列表甚至是普通无聊的整数。

这里还有一个红鲱鱼:如果你看一下 C#、Java 或 C 中的 monad 实现,它们比上面的 PHP 示例要长得多,也复杂得多。特别是,到处都有大量的类型,所以它看起来确实令人印象深刻。但丑陋的事实是:C#、Java 和 C 的类型系统实际上并不足以表达Monad. 特别是,Monad是 rank-2 多态类型,但 C# 和 Java 仅支持 rank-1 多态(他们称之为“泛型”,但它是同一回事),C 甚至不支持。

因此,monad 实际上在 C#、Java 和 C 中没有进行静态类型检查。(例如,这就是为什么 LINQ monad 理解被定义为模式而不是类型的原因:因为您根本无法在 C# 中表达类型。 ) 所有静态类型系统所做的,就是使实现更加复杂,而没有实际帮助。它需要更复杂的类型系统,例如 Haskell 的,才能获得 monad 的实际类型安全性。

注意:正如@Porges 指出的那样,我上面写的适用于泛型类型本身。monad您当然可以表达任何特定monad 的类型,例如Listor Maybe,但您不能表达其Monad自身的类型。这意味着您无法对“ ListIS-A Monad”的事实进行类型检查,并且您无法对适用于所有实例的通用操作进行类型检查Monad

(请注意,即使对于 Haskell 的类型系统,除了符合 monad类型之外,检查Monad它还遵守 monad法则可能太多了。您可能需要依赖类型,甚至可能需要一个成熟的自动定理证明器。)

于 2008-12-27T12:31:55.023 回答
0

正如您的问题标题所要求的那样,实现单子的语言肯定不是必须静态类型的。出于您概述的原因,这可能是一个好主意,但是在编译时未能检测到的错误从未阻止任何人。看看有多少人写PHP。

于 2008-12-27T06:01:55.997 回答
0

您需要关闭 State monad。我查了一下,PHP 从 5.3 开始就关闭了。这样就不再是问题了。

于 2010-05-15T02:43:06.933 回答
-3

不,在 php 中不可能实现单子。为此,您需要闭包。尽管如此,当您使用类模拟模式匹配时,Maybe 的概念仍然很有用:

abstract class Maybe {
        abstract public function isJust();
        public function isNothing(){
                return !$this->isJust();
        }
}

class Just extends Maybe {
        protected $val = null;
        public function __construct($val){
                $this->val = $val;

        }
        public function isJust(){
                return true;
        }
        public function getVal(){
                return $this->val;
        }

}
class Nothing extends Maybe {
        protected $val = null;
        public function __construct(){

        }
        public function isJust(){
                return false;
        }
}

function just(){
        print "isJust";
}
function nothing(){
        print "nothing";
}
function MaybeFunc(Maybe $arg){
        if(get_class($arg) == 'Just'){
                print "Just";
        } else {
                print "Nothing";
        }
}

MaybeFunc(new Just(5));
MaybeFunc(new Nothing());
于 2010-05-11T13:47:38.380 回答