2016-10-16 1 views
2

(.) und (<=<) sind ziemlich ähnlich:Anwendung von Funktionen und Kleisli Pfeile

(.) ::   (b -> c) -> (a -> b) -> (a -> c) 
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> (a -> m c) 

und sind als Methode in der Category Typklasse verfügbar ((->) und Kleisli Instanzen):

(<<<) :: (Category f) => f b c -> f a b -> f a c 

($) und sind auch ziemlich ähnlich:

($) ::   (a -> b) -> a -> b 
(=<<) :: Monad m => (a -> m b) -> m a -> m b 

Gibt es eine Typklasse, die diese Anwendungsfunktionen abstrahiert?

+1

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

Antwort

2

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).

3

Wie Daniels Kommentar sagt, umfasst bereits ($). Es gibt bereits eine newtype (ähnlich wie es ein Kleisli newtype für a -> m b für Category) für aIdentity genannt, die eine Monad Instanz hat, so dass

f $ x 

zu

Identity . f =<< Identity x 

entspricht Während es Unterkomponenten gibt, die in (.) und (<=<) (nämlich a -> b in der ehemaligen und in der letzteren), die zu einer Typenklasse für einen Typkonstruktor a :: * -> * -> * abstrahiert werden kann (was sich als Category herausstellt), die größte derartige Unterkomponente in ($) und ist nur a in der ersteren und m a in letzterer.