【问题标题】:Applicative instance for functions from same domain to Applicative来自同一域的函数的应用实例到 Applicative
【发布时间】:2014-11-01 11:39:07
【问题描述】:

假设我有一个适用的数据类型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

但是,我觉得应该有一种直接的无点写法,因为(-&gt; a) 是一个 Applicative Functor。

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

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

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

【问题讨论】:

    标签: haskell functional-programming typeclass


    【解决方案1】:

    关于Applicative 的一个简洁事实是这个类在组合下是封闭的。您可以从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
    

    您提出的(-&gt;) aApplicative 实例是这样的:

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

    现在,让我们扩展Compose ff &lt;*&gt; Compose fa :: Compose ((-&gt;) (A a)) A b(跳过一些步骤):

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

    所以你所做的实际上是(-&gt;) (A a)A 的组合。

    【讨论】:

    • 问题中的B a b等价于type B a = Compose ((-&gt;) (A a)) A对吗?
    • @ChristianConkle:是的。
    【解决方案2】:

    这个,大概?

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

    【讨论】:

      【解决方案3】:

      捎带 Luis Casillas 的回答:如果 B 确实是您正在使用的数据类型,您可以简单地使用 Compose ((-&gt;) (A a)) A 代替。数据构造函数的类型为Compose :: (A a -&gt; A b) -&gt; Compose ((-&gt;) (A a)) A b

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

      您可以与ComposeProductSum 和朋友一起玩很多有趣的 smooshing functors。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多