Dan*_*elM 8 haskell functional-programming typeclass
假设我有一个适用的数据类型A.(为了这个例子,我们可以假设A是Identity).
我现在有一个新的数据类型,对应于从一个A到另一个的"转换" :
data B a b = B (A a -> A b)
Run Code Online (Sandbox Code Playgroud)
我想定义一个普通的Applicative实例,(B a)它产生一个新的转换,它将两个参数应用于<*>它的输入,然后使用来自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
Run Code Online (Sandbox Code Playgroud)
但是,我觉得应该有一种直截了当的无意义的方式来编写这个使用(-> a)Applicative Functor 的事实.
作为我的想法的一个例子,考虑我对相应的Functor实例的定义:
instance Functor (B a) where
fmap f (B xtrans) = B $ (fmap f) <$> xtrans
Run Code Online (Sandbox Code Playgroud)
是否有一种类似的简单方法来定义Applicative实例?
Lui*_*las 12
其中一个很好的事实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
Run Code Online (Sandbox Code Playgroud)
您提出的Applicative实例(->) a是:
instance Applicative ((->) r) where
pure = const
ff <*> fa = \r -> let f = ff r
a = fa r
in f a
Run Code Online (Sandbox Code Playgroud)
现在,让我们扩展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
Run Code Online (Sandbox Code Playgroud)
所以你所做的实际上是(->) (A a)和的组成A.
这可能呢?
(B ftrans) <*> (B xtrans) = B ((<*>) <$> ftrans <*> xtrans)
Run Code Online (Sandbox Code Playgroud)