多种方法似乎可以解决Clojure的问题。例如,让我们定义一个plus函数,该函数添加数字但将其他字符串的字符串表示形式连接起来。
(defmulti plus (fn [& xs] (every? number? xs)))
(defmethod plus true [& xs] (apply + xs))
(defmethod plus false [& xs] (apply str xs))
(plus 1 8) ;9
(plus 1 \8) ;"18"
Run Code Online (Sandbox Code Playgroud)
多重方法是函数((ifn? plus)is true),因此也就象您希望的那样是一流的:
(let [z (partial plus 5)] (z \3)) ;"53"
Run Code Online (Sandbox Code Playgroud)
您可以使用 clojure 中的多方法或协议,或者使用 python 中的简单成员函数(类方法)来非常接近这一点。不过,haskell 中的每一项都缺少一个重要功能:返回类型多态性。
编译器知道您“期望”函数返回什么类型,并且可以相应地分派到不同的实现。这意味着使用相同参数调用的相同函数可以执行完全不同的操作,具体取决于对其返回值执行的操作。例如:
Prelude> read "[5,6,7]" :: [Int]
[5,6,7]
Prelude> read "[5,6,7]" :: [Double]
[5.0,6.0,7.0]
Run Code Online (Sandbox Code Playgroud)
同样,您甚至可以拥有多态常量,每个类型类实例都有不同的值:
Prelude Data.Word> (minBound, minBound, minBound) :: (Int, Bool, Word8)
(-9223372036854775808,False,0)
Run Code Online (Sandbox Code Playgroud)
您实际上无法用动态语言来做到这一点,因为没有类型推断。您可以通过传递代表“我想要的结果类型”的对象来稍微伪造它,并将它们用作您的调度程序,但实际上并不相同。