协议继承

时间:2014-12-19 18:46:22

标签: clojure protocols

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

  • 我想定义一个提供Functor功能的fmap接口。
  • 我想定义一个提供Applicativefapply功能的pure界面。

但每个applicative functor都是一个仿函数:(def fmap #(fapply (pure %1) %2))

我遇到的第一个解决方案如下:

  • FunctorApplicative定义为独立协议。
  • 定义functor?函数,该函数会为trueFunctor个实例返回Applicative
  • 定义fmap mulimethod,可以FunctorApplicative并发送 到#(functor/fmap %1 %2)#(applicative/fapply (applicative/pure %1) %2)

然而,这种解决方案闻起来像是在欺骗一个clojure型系统。

第二个解决方案是定义一个宏extend-applicative,它将自动实现Functor协议。但是这个解决方案看起来并不好看,因为它需要来自库用户的额外工作,并且它允许对functor / applicative实例进行sepparate定义,这很容易导致错误。

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

1 个答案:

答案 0 :(得分:2)

编辑:正如Thumbnail所说,这是一个错误的方法 - 我只是测试实现协议接口的记录,并没有注意到扩展了Applicative协议< / em>没有实际实现Functor。

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

的事情

Applicative.clj

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

functor.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。希望能帮助你实现目标。