clojure - 协议(protocol)继承

标签 clojure protocols

有时在接口(interface)上有一个继承结构很方便:
例如:

  • 我想定义一个 Functor提供fmap的接口(interface)功能。
  • 我想定义一个 Applicative提供fapply的接口(interface)和 pure职能。

  • 但是每个应用仿函数都是仿函数:(def fmap #(fapply (pure %1) %2)) .

    我来到的第一个解决方案如下:
  • 定义 FunctorApplicative作为独立的协议(protocol)。
  • 定义 functor?返回 true 的函数对于任何 FunctorApplicative实例。
  • 定义 fmap可以取Functor的muli方法或 Applicative和 dispatch
    #(functor/fmap %1 %2)#(applicative/fapply (applicative/pure %1) %2) .

  • 然而,这个解决方案看起来像是在欺骗 clojure 类型系统。

    第二种解决方案是定义一个宏extend-applicative这将自动实现 Functor协议(protocol)。但是这个解决方案看起来也不是很好,因为它需要库用户的额外工作,并且它允许单独定义仿函数/应用程序实例,这很容易导致错误。

    有没有更好的方法在clojure中表达这种关系?

    最佳答案

    编辑:正如 Thumbnail 所说,这被证明是一种错误的方法——我只是在测试实现协议(protocol)接口(interface)的记录,并没有注意到扩展 Applicative 协议(protocol)实际上并没有实现 Functor。

    请记住,extend不要求被扩展的类型是具体的实现;一个协议(protocol)可以扩展另一个协议(protocol),你也可以扩展接口(interface)和抽象类。你应该能够做类似的事情

    应用程序.clj

    (ns protocol.applicative)
    (defprotocol Applicative
          (fapply [f g])
          (pure [x] ))
    

    仿函数.clj
    (ns protocol.functor
      (:import [protocol.applicative.Applicative])
      (:require [protocol.applicative :refer [fapply pure]])
      )
    
    (defprotocol Functor
      (fmap [this f]))
    
    (extend-protocol Functor
      protocol.applicative.Applicative
        (fmap [this f] (fapply (pure f) this)))
    

    多个文件和导入是我尝试处理出现的一些编译顺序问题;您还必须将两者添加到 AOT。希望这可以帮助您使其正常工作。

    关于clojure - 协议(protocol)继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27572127/

    相关文章:

    clojure - 如何创建可配置的宏

    clojure - clojure 中全局变量的最佳实践(refs 与 alter-var-root)?

    ios - 为什么 tableView :cellForRowAtIndexPath: and tableView:heightForRowAtIndexPath: do not belong to the same protocol?

    swift - 如何使用私有(private)集扩展协议(protocol)?

    http - 流式传输 Http 请求的主体时如何处理错误

    objective-c - 如何将值传递给@protocol

    php - 在 PHP 中使用 HTTP 的 HEAD 命令最简单的方法是什么?

    clojure - 如何将时间打印为#inst

    java - Android 动态语言编程入门((J)Ruby、Clojure...)

    clojure - 我应该在 Clojure 中哪里使用 defrecord?