有时在接口上有一个继承结构很方便:
例如:
>我想定义一个提供fmap功能的Functor接口.
>我想定义一个Applicative接口,它提供了fapply和pure函数.
但是每个applicative functor都是一个仿函数:( def fmap#(fapply(pure%1)%2)).
我找到的第一个解决方案如下:
>将Functor和Applicative定义为独立协议.
>定义仿函数?函数,对任何Functor或Applicative实例返回true.
>定义fmap mulimethod,它可以使用Functor或Applicative并发送
到#(functor / fmap%1%2)或#(applicative / fapply(applicative / pure%1)%2).
然而,这种解决方案闻起来像是在欺骗一个clojure类型的系统.
第二种解决方案是定义一个宏扩展应用程序,它将自动实现Functor协议.但是这个解决方案看起来并不好看,因为它需要来自库用户的额外工作,并且它允许对functor / applicative实例进行sepparate定义,这很容易导致错误.
在clojure中有没有更好的方式来表达这种关系?
最佳答案 编辑:正如Thumbnail所说,这结果是一个错误的方法 – 我只是测试实现协议接口的记录,并没有注意到扩展Applicative协议实际上没有实现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.希望能帮助您实现目标.