繁体   English   中英

从相同域到Applicative的函数的应用实例

[英]Applicative instance for functions from same domain to Applicative

假设我有一个适用的数据类型A (为了这个例子,我们可以假设AIdentity )。

我现在有一个新的数据类型,对应于从A到另一个的“转换”:

data B a b = B (A a -> A b)

我想为(B a)定义一个普通的Applicative实例,它产生一个新的转换,它将<*>两个参数都应用到它的输入,然后使用来自A的Applicative实例的<*>的定义。

制定这个很简单:

instance Applicative (B a) where
    pure x = B $ const $ pure x

    (B ftrans) <*> (B xtrans) = B fxtrans 
        where fxtrans inp = let fout = ftrans inp
                                xout = xtrans inp
                            in  fout <*> xout

但是,我觉得使用(-> a)是一个Applicative Functor这一事实应该有一种直截了当的无意义的写法。

作为我的想法的一个例子,考虑我对相应的Functor实例的定义:

instance Functor (B a) where
    fmap f (B xtrans) = B $ (fmap f) <$> xtrans

是否有一种类似的简单方法来定义Applicative实例?

关于Applicative一个巧妙的事实是这个类在组合下是封闭的。 您可以从Data.Functor.Compose获取以下Data.Functor.Compose

newtype Compose f g a = Compose { getCompose :: f (g a) }

instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose fga) = Compose (fmap (fmap f) fga)

instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure a = Compose (pure (pure a))
    Compose f <*> Compose x = Compose $ (<*>) <$> f <*> x

您提出的(->) aApplicative实例是:

instance Applicative ((->) r) where
    pure = const
    ff <*> fa = \r -> let f = ff r
                          a = fa r
                      in f a

现在,让我们展开Compose ff <*> Compose fa :: Compose ((->) (A a)) A b (跳过一些步骤):

Compose ff <*> Compose fa
    == Compose $ (<*>) <$> ff <*> fa
    == Compose $ \r -> let f = ff r
                           a = fa r
                       in f <*> a

所以你所做的实际上是(->) (A a)A

这可能呢?

(B ftrans) <*> (B xtrans) = B ((<*>) <$> ftrans <*> xtrans)

回顾路易斯·卡西利亚斯的回答:如果B字面上是你正在使用的数据类型,你可以简单地使用Compose ((->) (A a)) A 数据构造函数的类型为Compose :: (A a -> A b) -> Compose ((->) (A a)) A b

您还可以使用类型同义词: type B a = Compose ((->) (A a)) A

你可以和ComposeProductSum和朋友一起玩很多有趣的smooshing仿函数。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM