在应用方面实施Monoidal

时间:2014-12-03 01:38:51

标签: haskell

Typeclassopedia提供以下练习:

  

以单位和(**)表示纯和(< *>),反之亦然。

此处MonoidalMyApplicative

class Functor f => Monoidal f where
  u :: f ()                          -- using `u` rather than `unit` 
  dotdot :: f a -> f b -> f (a,b)    -- using instead of `(**)`

class Functor f => MyApplicative f where
  p     :: a -> f a                  -- using instead of `pure`
  apply :: f (a -> b) -> f a -> f b  -- using instead of `(<**>)`

首先,让我展示Maybe - 类似的数据类型:

data Option a = Some a 
                | None deriving Show

然后,我定义了instance MyApplicative Option

instance MyApplicative Option where
  p                = Some
  apply None _     = None
  apply _ None     = None
  apply (Some g) f = fmap g f 

最后,我尝试根据Monoidal Option的{​​{1}}和p实施apply

MyApplicative

这是对的吗?我instance Monoidal Option where u = p () dotdot None _ = None dotdot _ None = None dotdot (Some x) (Some y) = Some id <*> Some (x, y) dotdot的实施似乎不是

apply

特别是,我很好奇如何使用Applicative instance Monoidal Option where u = p () dotdot None _ = None dotdot _ None = None dotdot (Some x) (Some y) = apply (Some id) (Some (x, y)) 正确实施dotdot :: f a -> f b -> f (a, b) - 在我的情况下(<*>)

1 个答案:

答案 0 :(得分:10)

ApplicativeMonoidal的简洁替代演示文稿。两个类型类都是等价的,您可以在两者之间进行转换,而不考虑像Option这样的特定数据类型。 &#34;整洁的替代演示&#34; for Applicative基于以下两个等价

pure a = fmap (const a) unit
unit = pure ()

ff <*> fa = fmap (\(f,a) -> f a) $ ff ** fa
fa ** fb = pure (,) <*> fa <*> fb

获得这个&#34;整洁的替代演示文稿&#34; for ApplicativezipWith的技巧相同 - 将接口中的显式类型和构造函数替换为可以传递类型或构造函数的东西,以恢复原始接口的内容。

unit :: f ()

替换为pure,我们可以将()类型和构造函数() :: ()替换为unit

pure :: a  -> f a
pure    () :: f ()

同样(尽管不是那么简单)将类型(a,b)和构造函数(,) :: a -> b -> (a,b)替换为liftA2以恢复**

liftA2 :: (a -> b -> c) -> f a -> f b -> f c
liftA2    (,)           :: f a -> f b -> f (a,b)

Applicative然后通过将函数应用程序<*>提升到仿函数中来获取漂亮的($) :: (a -> b) -> a -> b运算符。

(<*>) :: f (a -> b) -> f a -> f b
(<*>) = liftA2 ($)

<*>回到liftA2已经足够liftA2 is included in Control.Applicative了。 <$>是中缀fmap

liftA2 :: Applicative f => (a -> b -> c) -> f a -> f b -> f c
liftA2 f a b = f <$> a <*> b