这是关于 Clojure 与 Haskell 等其他语言的表达能力的问题。更广泛的问题是Expression Problem 的解决方案。
This question得出的结论是,通常 Clojure 协议(protocol)(和多方法)不如 Haskell 类型类具有表达性,因为协议(protocol)在第一个参数上分派(dispatch),而 Haskell 类型类可以在返回类型上分派(dispatch)。 (现在我觉得这个推理真的很有趣,对发动语言 war 没有兴趣。我只对思路清晰感兴趣)。
作为打破这种推理的一部分 - 我的问题是 - 我们不能创建一个按返回类型调度的 Clojure 多方法 (或输入提示)。我认为我们可以将以下表达式放入 Clojure 多方法中:
(= java.lang.String (:tag (meta #'my-string)))
函数是:
(defn ^String my-string []
"hello world")
编辑:
关键是我可以运行:
(meta #'my-string)
并在没有函数评估的情况下得到以下结果:
{:arglists ([]), :ns #<Namespace push-price.core>, :name my-string, :column 1,
:line 1, :file "/private/var/folders/0l/x6hr0t1j2hvcmm_sqq04vdym0000gn/T/form-
init7576840885484540032.clj", :tag java.lang.String}
即我有一些关于我的函数的预期类型的信息,但没有对其进行评估。
编辑 3(2014 年 4 月 24 日):
假设我有以下类型:
(deftype 字符串类型 [])
(deftype int-type [])
然后我根据这些类型定义了以下函数:
(defn #^{:return-type string-type} return-string []
"I am returning a string")
(defn #^{:return-type int-type} return-int []
42)
现在我编写一个函数来调度它们的返回类型,如下所示:
(defn return-type-dispatch [fn-arg]
(let [return-type (:return-type (meta fn-arg))]
(cond
(= return-type string-type)
"This function has a return type of the string type"
(= return-type int-type)
"This function has a return type of the integer type"
:else (str "This function has a return type of:" return-type))))
然后我写一个宏在编译时运行它
(defmacro compile-time-type-check-string []
(println (return-type-dispatch #'return-string)))
(compile-time-type-check-string)
然后我像这样测试它:
lein uberjar
这给出了以下结果:
$ lein uberjar
Compiling dispatch-type-compile-time.core
This function has a return type of:class dispatch_type_compile_time.core.string-type
...
所以我似乎是在返回类型上进行调度。
最佳答案
让我们想象一下 Clojure 中有返回类型的多态性。这将允许我们编写类似 Haskell 类的东西
class Default a where def :: a
在 Haskell 中这是有效的,因为它是一个编译时错误,有一个片段
def
因为众所周知,在编译时这意味着什么是模棱两可的。类似地,如果我们要编写 Clojure 片段
(def)
不可能知道如何将该调用分派(dispatch)给正确的实例。更清楚地说,Clojure 的评估顺序是片段中的
(foo x y z)
表达式
x
, y
, 和 z
在 foo
之前获得所有评估.为了 (def)
要工作,它需要以某种方式检查 foo
(并因此强制其评估)以获得有关 (def)
的返回值的信息将会被使用。这可以在 CPS 转换后完成,在这种情况下
(def)
将被转换成一个函数,如(在 Haskell 类型符号中)class Default a where def :: (a -> r) -> r
现在我们看到我们可以检查延续函数,以了解有关它期望的参数类型的信息,然后将其发送出去。
最后,只要有足够的宏魔法,就可以做到这一点……但现在可能比在 Clojure 上实现 Haskell 风格的类型系统更省力。类型化的 Clojure 可能是一个很好的模型,除非它被显式设计,因此 Clojure 的语义不会受到推断类型的影响。这正是返回类型多态中发生的情况,因此在 Typed Clojure 中显然是不可能的。
关于haskell - Clojure - 按返回类型分派(dispatch)? (与 Haskell 类型类一样富有表现力),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22740178/