Sowohl Ihre Beispiele sind Pfeil Zuordnungen von functors (nicht Functors
, aber functors im weiteren kategorischen Sinn), wie fmap
der Pfeil Abbildung eines Functor
ist. Beispielsweise ist die Pfeilabbildung eines Funktors von Kleisli m
zu (->)
für einige Monade m
. Eine entsprechende Verallgemeinerung ist dann eine, die Funktoren zwischen verschiedenen Kategorien berücksichtigt. Control.Categorical.Functor
sieht vor, dass:
class (Category r, Category t) => Functor f r t | f r -> t, f t -> r where
fmap :: r a b -> t (f a) (f b)
Bewaffnet mit, dass, würden Sie in der Lage sein, eine Instanz im Geiste zu schreiben: Sie können
-- `(.)` is plain old Prelude `(.)`, and not the generalised `Category` one.
instance Monad m => Functor m (Kleisli m) (->) where
fmap = (=<<) . runKleisli
Oder für etwas wirklich laufen:
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Arrow (Kleisli(..))
import qualified Control.Categorical.Functor as F
newtype BindF m a = BindF { runBindF :: m a }
deriving (Functor, Applicative, Monad, Show)
instance Monad m => F.Functor (BindF m) (Kleisli (BindF m)) (->) where
fmap = (=<<) . runKleisli
GHCi> F.fmap (Kleisli (BindF . replicate 2)) (BindF [1,2,3])
BindF {runBindF = [1,1,2,2,3,3]}
Eine ähnliche Instanz könnte für in geschrieben werden Haltung, für (<*>)
, in Bezug auf die Kategorie Static
. Wie für ($)
ist es die Pfeilabbildung des Identitätsfunktors in (->)
, und so ist es nur fmap
für Identity
sans Identity
Wrapper (vgl. Daniel Wagners Kommentar zu der Frage).
Mit geeigneten Erweiterungen und Importe, '($) :: forall a b.(a -> b) -> a -> b; ($) = coerce ((= <<) @Identity @a @b) 'ist eine vollkommen akzeptable Definition von' ($) '. In gewisser Weise ist> Monad