Clojure - 返回类型的调度? (与 Haskell 类型类一样具有表现力)

2024-01-07

这是一个关于 Clojure 与 Haskell 等其他语言的表达能力的问题。更广泛的问题是解决表达问题 http://en.wikipedia.org/wiki/Expression_problem

这个问题 https://stackoverflow.com/questions/22040115/what-are-the-reasons-that-protocols-and-multimethods-in-clojure-are-less-powerfu得出的结论是,一般来说,Clojure 协议(和多方法)的表达能力不如 Haskell 类型类,因为协议在第一个参数上分派,而 Haskell 类型类可以在返回类型上分派。 (现在我觉得这个推理真的很有趣,并没有兴趣发起一场语言战争。我只是对思路清晰感兴趣)。

作为打破这个推理的一部分 - 我的问题是 -我们不能制作一个按返回类型分派的 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)

不可能知道如何将该调用分派到正确的实例。更清楚地说,Clojure 的求值顺序是片段中的顺序

(foo x y z)

表达式x, y, and z在之前进行所有评估foo。为了(def)要工作它需要以某种方式检查foo(从而强制其评估)以获得有关返回值如何的信息(def)将会被使用。

这可以在 CPS 转换后完成,在这种情况下(def)会被转换成一个类似的函数(用 Haskell 类型表示法)

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

现在我们看到我们可以检查延续函数,以了解有关它期望的参数类型的信息,然后将其分派出去。

最后,如果有足够的宏观魔力,这是可以做到的……但目前可能比在 Clojure 上实现 Haskell 风格的类型系统要省力。类型化 Clojure 可能是一个很好的模型,只不过它经过明确设计,使得 Clojure 的语义不会受到推断类型的影响。这是exactly返回类型多态性会发生什么,因此在 Typed Clojure 中显然是不可能的。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Clojure - 返回类型的调度? (与 Haskell 类型类一样具有表现力) 的相关文章

随机推荐

  • UIButton 在 iOS 5 中不调用操作,但在 iOS 6 中工作

    我有一个UIButton从 xib 文件加载IBOutlet视图控制器的属性 我将一个选择器附加到viewDidLoad我的视图控制器 myButton addTarget self action selector mySelector f
  • ASP.NET 动态生成的 TableRows 在回发之间不会保留

    在 ASPX 中
  • 使用 PHP 的 Salesforce 标注

    抱歉 因为我可能不知道 salesforce API 的术语 我刚刚开始编写一个连接器来与销售人员交互 但我陷入了困境 我有一个要求 每次将新条目添加到潜在客户部分时 我都必须检索几个字段 名字和产品代码 并将其传递给使用 PHP 的不同软
  • Azure Functions 如何将应用程序设置添加到绑定

    我正在尝试使用我的 Azure 函数的应用程序设置添加一些自定义绑定 我只需要从我的设置中接收字符串 我想从我的设置中获取 simpleValue bindings name someValue type stringSetting con
  • MySQL,无法创建 UNIX 套接字 (12)

    SQLSTATE HY000 2001 Can t create UNIX socket 12 在我的本地计算机上 我的项目运行良好 当我将更改推送到服务器后 我收到此错误消息 mysql日志完全是空的 mysql配置 my cnf htt
  • 什么是 LLVM 元数据

    这些可能是非常基本的问题 1 什么是 LLVM 元数据以及如何在我的程序中使用它 我已阅读所有文档 但我不明白如何使用它 2 如何在文件中添加我的个人元数据 提前致谢 最好的信息来源是 2010 年将元数据引入 LLVM IR 的博客文章
  • NSURLRequest 中不支持的 URL

    如果我从终端运行此请求 我可以正常看到 JSON 请求 curl XGET 192 168 0 6 8888 scripts data backend2 index php name all 我的 NSURlRequest 代码是这样的 N
  • SSE 比较内在函数 - 如何从比较中得到 1 或 0?

    我正在尝试使用 SSE 内在函数编写相当于 if 语句的内容 我在用 m128 mm cmplt ps m128 a m128 b 进行比较 a 0xffffffff or 0x0如果比较分别为真或假 我想将这些值转换为 1 和 0 为了做
  • 如何在 wso2 中迭代 JSON 负载并构建响应

    如何通过将 carValue 和 bikeValue 添加到响应数组的 id C 05 B 08 C 07 B 06 中来迭代结果数组并构造响应数组 并保持与描述相同的 desc JSON 负载请求 results desc Blind c
  • 在便携式草莓上安装 Gtk2

    我下载了 strawberry perl 5 12 2 0 portable 和 gtk bundle 2 22 1 20101227 win32 我在某个目录中提取了草莓 perl 并在那里放置了包含 gtk 内容的 gtk 文件夹 在p
  • 以编程方式使用 Sim1 或 Sim2 发送短信的选项

    我有一部带有 2 张 SIM 卡的 Android 手机 我想使用 Sim1 或 Sim2 发送短信 默认情况下 消息是从 sim1 发送的 但我想从 sim2 发送短信 是否可以设置使用Sim1或Sim2发送短信 如果有一个设置选项可以使
  • C++ 中的 getline() - 不需要 _GNU_SOURCE?

    首先 我对 C 还很陌生 我相信getline 不是标准 C 函数 所以 define GNU SOURCE需要使用它 我现在使用 C g 告诉我 GNU SOURCE已经定义 g Wall Werror parser cpp parser
  • 使用 maven 构建 apk 时出现 ClassNotFoundException

    我想在 Android 开发中切换到 Maven 进行构建过程 我跟着http www sonatype com books mvnref book reference android dev sect archetype html htt
  • 在 matplotlib 中,为什么用细线绘图更快?

    我今天偶然发现了这一点 如果线宽小于 1 0 在 matplotlib 中绘制线条似乎要快得多 我只在Mac上测试过这个 但效果似乎很强 例如 如果您尝试此代码 您将发现线宽为 0 5 时数据绘制速度比线宽 1 0 快约 10 倍 impo
  • 如何使 org-protocol 在 Openbox 上工作?

    I tried 说明 http orgmode org worg org contrib org protocol html 我正在使用 FirefoxLubuntu https en wikipedia org wiki Lubuntu
  • 在c++中将高斯曲线拟合到某个直方图峰值

    我有两个关于将高斯曲线拟合到直方图峰值的问题 我的第一个问题是一个非常基本的问题 如何将高斯曲线拟合到整个直方图 这是否仅仅意味着我必须找出并计算直方图的平均值 和偏差 并将它们放入高斯曲线的公式中 下面的例子正确吗 假设 仅作为示例 我有
  • CSS 弹性框最后一个空格被删除

    通过设置display的一个项目到flex我发现最后一个空格已从文本字符串中删除 div class has flex Some text a href link Link a div Becomes div class has flex
  • 有没有办法只在 Tomcat/Wildfly/Glassfish 启动时运行方法/类?

    我需要在 Tomcat 启动时删除临时文件 包含临时文件的文件夹的传递位于 applicationContext xml 中 有没有办法只在 Tomcat 启动时运行方法 类 你可以写一个ServletContextListener它从调用
  • iOS SDK 中的通知中心与委托

    为什么 Apple 选择使用委派来进行 SDK 对象之间的某些通信 并为其他对象将通知发布到通知中心 特别是 我正在考虑来自 UIWindow 的一组键盘外观通知 是否因为通知中心系统意味着多个对象可以使用键盘外观操作作为触发器来更改其状态
  • Clojure - 返回类型的调度? (与 Haskell 类型类一样具有表现力)

    这是一个关于 Clojure 与 Haskell 等其他语言的表达能力的问题 更广泛的问题是解决表达问题 http en wikipedia org wiki Expression problem 这个问题 https stackoverf