更广泛地说,这个问题是关于表达问题的各种方法。这个想法是您的程序是数据类型和对它的操作的组合。我们希望能够在不重新编译旧类的情况下添加新案例。
现在 Haskell对TypeClass的表达式问题有了一些非常棒的解决方案。特别是 - 我们可以这样做:
class Eq a where
(==) :: a -> a -> Bool
(/=) :: a -> a -> Bool
member :: (Eq a) => a -> [a] -> Bool
member y [] = False
member y (x:xs) = (x == y) || member y xs
现在在Clojure中有多种方法- 所以你可以这样做:
(defmulti area :Shape)
(defn rect [wd ht] {:Shape :Rect :wd wd :ht ht})
(defn circle [radius] {:Shape :Circle :radius radius})
(defmethod area :Rect [r]
(* (:wd r) (:ht r)))
(defmethod area :Circle [c]
(* (. Math PI) (* (:radius c) (:radius c))))
(defmethod area :default [x] :oops)
(def r (rect 4 13))
(def c (circle 12))
(area r)
-> 52
(area c)
-> 452.3893421169302
(area {})
-> :oops
同样在 Clojure 中,您有协议- 您可以使用这些协议:
(defprotocol P
(foo [x])
(bar-me [x] [x y]))
(deftype Foo [a b c]
P
(foo [x] a)
(bar-me [x] b)
(bar-me [x y] (+ c y)))
(bar-me (Foo. 1 2 3) 42)
=> 45
(foo
(let [x 42]
(reify P
(foo [this] 17)
(bar-me [this] x)
(bar-me [this y] x))))
=> 17
现在这个人提出索赔:
但是,有协议和多种方法。它们非常强大,但不如 Haskell 的类型类强大。您可以通过在协议中指定您的合同来引入类型类之类的东西。这仅在第一个参数上分派,而 Haskell 可以在整个签名上分派,包括返回值。多方法比协议更强大,但不如 Haskell 的调度强大。
我的问题是:Clojure 中的协议和多方法在多态性方面不如 Haskell 中的类型类强大的原因是什么?