haskell - 来自同一域的函数的应用实例到 Applicative

标签 haskell functional-programming typeclass

假设我有一个数据类型 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) 的事实。是一个应用仿函数。

作为我的想法的一个示例,请考虑我对相应 Functor 实例的定义:
instance Functor (B a) where
    fmap f (B xtrans) = B $ (fmap f) <$> xtrans

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

最佳答案

关于 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
Applicative (->) a 的实例,你提出来的,是这样的:
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 .

关于haskell - 来自同一域的函数的应用实例到 Applicative,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26683564/

相关文章:

f# - 在F#中枢转或压缩seq <seq <'a >>

functional-programming - 累积vs折叠vs减少vs压缩

haskell - 在 Haskell 中覆盖 fromInteger

haskell - 指数函数的简单实现

haskell - 在 ghci 中为与模块相关的命令指定包名

haskell - 如何在 Haskell 中获取程序的运行时间

functional-programming - Racket - 构建内置成员函数

user-interface - 函数式 GUI 编程可能吗?

haskell - 在 Haskell 中为类型别名派生 Eq 和 Show

haskell - Haskell 中的抽象类型类在哪些方面可以使困难的事情变得更容易?