Reputation: 41
Sometimes it is convenient to have an inheritance structure on interfaces: For example:
Functor
interface which provides fmap
function.Applicative
interface which provides fapply
and pure
functions.But every applicative functor is a functor: (def fmap #(fapply (pure %1) %2))
.
The first solution I came to is the following:
Functor
and Applicative
as independent protocols.functor?
function which returns true
for any Functor
or Applicative
instance.fmap
mulimethod which can take Functor
or Applicative
and dispatches
to #(functor/fmap %1 %2)
or #(applicative/fapply (applicative/pure %1) %2)
.However this solutions smells as it looks like cheating a clojure type system.
The second solution is to define a macro extend-applicative
which will automatically implement Functor
protocol. But this solution do not look great also as it requires additional work from user of the library and it allows sepparate definition of functor/applicative instances which can easily lead to an error.
Is there a better way to express this kind of relations in clojure?
Upvotes: 4
Views: 1221
Reputation: 3014
EDIT: As Thumbnail says, this turned out to be a faulty approach - I was only testing records implementing the protocol interface and didn't notice that extending the Applicative protocol didn't actually implement Functor.
Remember, extend
does not require that the type being extended is a concrete implementation; one protocol can extend anotheryou can extend interfaces and abstract classes, too. You should be able to do something like
(ns protocol.applicative)
(defprotocol Applicative
(fapply [f g])
(pure [x] ))
(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)))
Multiple files and importing is my attempt to deal with some compilation order issues which come up; you'll also have to add the two to AOT. Hope that helps you get it working.
Upvotes: 3