有时在接口(interface)上有一个继承结构很方便:
例如:
Functor
提供fmap
的接口(interface)功能。 Applicative
提供fapply
的接口(interface)和 pure
职能。 但是每个应用仿函数都是仿函数:
(def fmap #(fapply (pure %1) %2))
.我来到的第一个解决方案如下:
Functor
和 Applicative
作为独立的协议(protocol)。 functor?
返回 true
的函数对于任何 Functor
或 Applicative
实例。 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/