实现Monads的语言必须是静态类型吗?

时间:2008-12-27 05:51:31

标签: functional-programming monads static-typing

我正在学习函数式编程风格。在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 个答案:

答案 0 :(得分:26)

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

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

正如你可以从选择上面的例子中看出的那样,我(大多数时候)是一个Ruby程序员。所以,就像一个笑话一样,我采用了上面的一个例子并用一种我知道绝对没有的语言重新实现它,这通常被认为是一种不是很强大的语言,而且似乎是地球上唯一一个我无法找到Monad教程的编程语言。我可以告诉你...... PHP中的身份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的语言进行类型检查。否则,在编译期间无法找到类型错误,并且不控制“复杂性”。我的理解是否正确?

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

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

因此,monad实际上不是在C#,Java和C中进行静态类型检查。(例如,LINQ monad理解被定义为模式而不是类型的原因:因为你根本无法表达 C#中的类型。)所有静态类型系统都会使实现变得更复杂,而实际上并没有帮助。它需要一个更复杂的类型系统,如Haskell,以获得monad的实际类型安全性。

注意:正如@Porges指出的那样,我在上面仅所写的内容适用于通用monad类型本身。您当然可以表达任何特定 monad的类型,例如ListMaybe,但您无法表达Monad本身的类型。这意味着您无法键入 - 检查“List IS-A Monad”这一事实,并且您无法键入检查适用于Monad所有实例的通用操作。

(请注意,除了符合monad 类型之外,检查Monad是否也遵守monad 定律对于Haskell的类型系统来说可能太多了。你可能需要依赖类型,甚至可能需要一个完整的自动定理证明器。)

答案 1 :(得分:0)

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

答案 2 :(得分:0)

你需要关闭State monad的闭包。我查了一下,PHP自5.3以来已经关闭了。所以那不再是问题了。

答案 3 :(得分:-3)

不,在php中无法实现monads。你需要关闭它。但是,当您使用类模拟模式匹配时,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());