2

(.)并且(<=<)非常相似:

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

并且可以作为Category类型类((->)Kleisli实例)中的方法使用:

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

($)并且(=<<)也非常相似:

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

是否有抽象这些应用程序功能的类型类?

4

2 回答 2

3

正如丹尼尔的评论所说,(=<<)已经包含($). 已经有一个新类型(类似于Kleislifora -> m b的新类型Categorya被调用Identity,它有一个Monad这样的实例

f $ x

对应于

Identity . f =<< Identity x

虽然在(.)and中重用了一些子组件(<=<)(即a -> b在前者和a -> m b后者中),它们可以抽象为类型构造函数的类型类a :: * -> * -> *(结果是),但在andCategory中最大的此类子组件只是在前者中在后者中。($)(=<<)am a

于 2016-10-16T00:23:53.013 回答
2

你的两个例子都是函子的箭头映射(不是Functors,而是更广泛分类意义上的函子),就像fmapa 的箭头映射一样Functor(=<<),例如,是某个 monad的函子从Kleisli m到的箭头映射。因此,适当的概括是解释不同类别之间的函子的概括。规定:(->)mControl.Categorical.Functor

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)

有了它,您将能够本着以下精神编写一个实例:

-- `(.)` is plain old Prelude `(.)`, and not the generalised `Category` one.
instance Monad m => Functor m (Kleisli m) (->) where
    fmap = (=<<) . runKleisli

或者,对于您可以实际运行的东西:

{-# 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]}

类似的例子可以写成,例如,(<*>)Static类别而言。至于($),它是 中恒等函子的箭头映射(->),因此它仅fmap适用于Identity没有Identity包装器(参见 Daniel Wagner 对问题的评论)。

于 2016-10-16T00:43:20.097 回答