功能和Kleisli箭头的应用

时间:2016-10-16 00:02:02

标签: haskell typeclass kleisli

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

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

是否有一个类型类抽象出这些应用程序函数?

2 个答案:

答案 0 :(得分:3)

正如丹尼尔的评论所说,(int*)ap已经包含 %1 = tail call i8* @malloc(i64 4) ... %8 = tail call i32 (i8*, ...) @printf(i8* nonnull getelementptr inbounds ([10 x i8], [10 x i8]* @.str.1, i64 0, i64 0), i8* %1, i8* %1, i8* %1) 。已经存在一个新类型(类似(=<<) ($) Kleisli a -> m b的{​​{1}}新类型Category a名为Identity,其Monad f $ x

这样的实例
Identity . f =<< Identity x

对应

(.)

虽然有些子组件在(<=<)a -> b中重复使用(前者为a -> m b,后者为a :: * -> * -> *),但可以将其抽象为类型类对于类型构造函数Category(原来是($)),(=<<)a中最大的此类子组件在前者中仅为m a且{ {1}}在后​​者中。

答案 1 :(得分:2)

您的示例都是仿函数的箭头映射(不是Functors,而是更广泛的分类意义上的仿函数),就像fmapFunctor的箭头映射一样。例如,(=<<)是针对某些monad Kleisli m的仿函数从(->)m的箭头映射。因此,适当的概括是考虑不同类别之间的仿函数的概括。 Control.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类别而言,可能会为(<*>)编写类似的实例。对于($),它是(->)中标识仿函数的箭头映射,因此fmapIdentity没有Identity包装器(cf丹尼尔瓦格纳对这个问题的评论。

相关问题