Clojure - dispatch在返回类型? (表示为Haskell类型类) [英] Clojure - dispatch on return type? (As expressive as Haskell Typeclasses)

查看:216
本文介绍了Clojure - dispatch在返回类型? (表示为Haskell类型类)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是一个关于Clojure与其他语言(如Haskell)的表达力的问题。更广泛的问题是表达式问题的解决方案



此问题得出结论,一般来说,Clojure协议(和多方法)比Haskell类型类表达式更少,因为协议在第一个参数上调度,而Haskell类型类可以在返回类型上调度。 (现在我认为这个推理真的很有趣,没有兴趣开始一场语言战争,我只是对思想的清晰感兴趣)。



作为打破这个推理的一部分 - 我的问题是 - 不能我们制作一个Clojure multimethod分派在返回类型暗示)。我想我们可以把以下表达式放入Clojure多重方法中:

 (= java.lang.String(:tag(meta#'my-string)))

其中函数是:

 (defn ^ String my-string [] 
hello world)






编辑:
关键是我可以运行:

 (meta#'my-string)

并获得无功能评估的以下结果:



< pre class =lang-lisp prettyprint-override> {: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 string-type [])

  deftype int-type [])

然后我根据这些类型定义了以下函数: / p>

 (defn#^ {:return-type string-type} return-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)
此函数具有字符串类型的返回类型
(= return-type int-type)
此函数具有整数类型的返回类型
:else(str此函数具有返回类型:return-type))))



然后我写一个宏在编译时运行

 (defmacro compile-time-type-check-string [] 
(println(return-type-dispatch#'return-string)))

(编译时类型检查字符串)

  lein uberjar 

这会产生以下结果:

  $ lein uberjar 
编译dispatch-type-compile-time.core
此函数的返回类型为:class dispatch_type_compile_time.core.string-type
...

所以我似乎是在返回类型分派。

解决方案

让我们假设在Clojure中有返回类型多态性。这将允许我们写像Haskell类

  class默认a其中def :: a 



在Haskell这是工作,因为它是一个编译时错误,有一个像

  def 

因为在编译时已知不明确时间就是什么意思。同样,如果我们要写Clojure片段

 (def)

它不可能知道如何调度该调用到正确的实例。要更清楚,Clojure的评估顺序是

 (foo xyz)

表达式 x y z 获得所有之前的 foo 。为了使(def)工作,它需要以某种方式检查 foo (并因此强制其评估)以获取有关如何使用(def)的返回值的信息。



这可以在CPS转换,在这种情况下(def)将被转换为一个函数(在Haskell类型符号中)

  class Default a where def ::(a  - > r) - > r 

现在我们可以看到,我们可以检查继续函数,以了解信息类型



最后,给定足够的宏魔法可以做到这一点,但可能现在比实现Haskell-在Clojure之上的风格类型系统。类型化Clojure可以是一个很好的模型,除非它被明确设计,使得Clojure的语义不会受到推断类型的影响。这是确切在返回类型多态性会发生什么,所以它在类型Clojure中显然是不可能的。


This is a question about the expressiveness of Clojure vs other languages such as Haskell. The broader issue is solutions to the Expression Problem

This question reached the conclusion that in general Clojure protocols (and multimethods) were less expressive than Haskell typeclasses because protocols dispatched on first argument, and Haskell typeclasses could dispatch on return type. (Now I think this reasoning is really interesting, and have no interest in starting a language war. I'm just interested in clarity of thought).

As part of breaking this reasoning down - my question is - can't we make a Clojure multimethod that dispatches on return type (or type hint). I think we can put the following expression into a Clojure multimethod:

(= java.lang.String (:tag (meta #'my-string)))

where the function is:

(defn ^String my-string [] 
  "hello world")


Edit: The point is that I can run:

(meta #'my-string)

and get the the following result without function evaluation:

{: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}

ie I have some information about the intended type of my function without evaluating it.


Edit 3 (24 Apr 2014):

Suppose I have the following types: (deftype string-type [])

(deftype int-type [])

Then I have the following functions defined in terms of these types:

(defn #^{:return-type string-type} return-string [] 
  "I am returning a string")

(defn #^{:return-type int-type} return-int [] 
  42)

Now I write a function to dispatch on their return type like so:

(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))))

Then I write a macro to run it at compile-time

(defmacro compile-time-type-check-string []
  (println (return-type-dispatch #'return-string)))

(compile-time-type-check-string)

Then I test it like so:

lein uberjar

This gives the following result:

$ lein uberjar
Compiling dispatch-type-compile-time.core
This function has a return type of:class dispatch_type_compile_time.core.string-type
...

So I appear to be dispatching on return type.

解决方案

Let's imagine there were return type polymorphism in Clojure. That would allow us to write something like the Haskell class

class Default a where def :: a

In Haskell this works because it's a compile-time error to have a fragment like

def

as it's known to be ambiguous at compile time as to what that means. In a similar vein, if we were to write the Clojure fragment

(def)

it'd be impossible to know how to dispatch that call to the proper instance. To be more clear, the evaluation order for Clojure is that that in the fragment

(foo x y z)

the expressions x, y, and z get evaluated all prior to foo. In order for (def) to work it would need to somehow examine foo (and thus force its evaluation) in order to get information about how the return value of (def) will be used.

This could be done after a CPS transformation in which case (def) would be transformed into a function like (in Haskell type notation)

class Default a where def :: (a -> r) -> r

and now we see that we could examine the continuation function in order to learn information aobut the type of the parameter it expects and then dispatch off of that.

Finally, given enough macro magic this could be done... but likely for now less effort than implementing a Haskell-style type system atop Clojure. Typed Clojure could be a great model for this except it's been explicitly designed so that the semantics of Clojure cannot be affected by the inferred types. This is exactly what happens in return type polymorphism and so it's explicitly impossible in Typed Clojure.

这篇关于Clojure - dispatch在返回类型? (表示为Haskell类型类)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆