当前位置 : 主页 > 大数据 > 区块链 >

Clojure中的协议和多方法与Haskell中的类型类型的多态性相比不太强大的原因是什

来源:互联网 收集:自由互联 发布时间:2021-06-22
更广泛地说,这个问题是关于 expression problem的各种方法。这个想法是您的程序是数据类型和操作的组合。我们希望能够添加新的案例,而不需要重新编译旧的类。 现在,Haskell有一个非
更广泛地说,这个问题是关于 expression problem的各种方法。这个想法是您的程序是数据类型和操作的组合。我们希望能够添加新的案例,而不需要重新编译旧的类。

现在,Haskell有一个非常棒的解决方案expression problem与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有multimethods – 所以你可以做:

(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你有protocols – 你可以做什么:

(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

现在this individual makes the claim:

But, there are protocols and multi-methods. These are very powerful, but not as powerful as Haskell’s typeclasses. You can introduce something like a typeclass by specifying your contract in a protocol. This only dispatches on the first argument, whereas Haskell can dispatch on the entire signature, including return value. Multi-methods are more powerful than protocols, but not as powerful as Haskell’s dispatch.

我的问题是:Clojure中的协议和多方法与Haskell中的类型类型相比,多态性的功能不那么强大?

那么明显的一点是,协议只能在第一个参数和唯一的第一个参数上调度。这意味着它们大致相当于

class Foo a where
   bar  :: a -> ...
   quux :: a -> ...
   ...

哪里必须是第一个参数。 Haskell的类型类可以出现在函数的任何位置。所以协议比类型很容易表达。

接下来是多方法。多方法,如果我没有错误,允许基于所有参数的函数进行调度。这在某些方面看起来比Haskell更具表现力,因为您可以不同地分派相同类型的参数。然而,这实际上可以在Haskell中完成,通常通过将参数包装在用于调度的新类型中。

一些不能用多方法知道我做的事情:

>返回类型调度
>将所有类型的类型的值存储在多个数据库中forall a。 Foo a =>一个

要看看如何进入,考虑Monoid它有一个值mempty :: Monoid m =>米这不是一个功能,并且由于我们没有关于我们期望选择的方法的任何类型信息,因此对Clojure进行模拟是不可能的。

对于2.考虑读::读a =>字符串 – >一个。在Haskell中,我们实际上可以创建一个类型为[forall a。读a => a],我们基本上推迟了计算,我们现在可以运行并重新运行列表的元素,尝试将它们读取为不同的值。

类型类也有静态类型,所以有一些检查,以确保你不会最终“卡住”没有一个实例静态调用,但Clojure是动态类型,所以我将粉笔这两者之间的风格的差异语言而不是一种特殊的优势。当然,类型类比多方法具有更少的开销的优点,因为通常可以内联证件记录,并且一切都被静态地解析。

网友评论