Protocol inheritance

Sometimes it is convenient to have an inheritance structure on interfaces: For example:

  • I want to define an interface Functorthat provides a function fmap.
  • I want to define an interface Applicativethat provides functions fapplyand pure.

But each application is a functor: (def fmap #(fapply (pure %1) %2)).

The first solution I came to is the following:

  • Define Functorand Applicativeas independent protocols.
  • Define a function functor?that returns truefor any instance of Functoror Applicative.
  • Define a fmapmulimethod that can accept Functoreither Applicativeand sends before #(functor/fmap %1 %2)or #(applicative/fapply (applicative/pure %1) %2).

However, these solutions smell like it is like cheating a system like clojure.

The second solution is to define a macro extend-applicativethat will automatically implement the protocol Functor. But this solution does not look very good, because it requires additional work from the library user and allows you to separate the definition of functional / applicative instances, which can easily lead to an error.

Is there a better way to express such a relationship in clojure?

+4
source share
1 answer

EDIT: As the thumbnail says, this turned out to be an erroneous approach - I only tested records that implement the protocol interface, and did not notice that the extension of the Applicative Protocol did not actually implement 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. , .

+2

Source: https://habr.com/ru/post/1568375/


All Articles