Sag*_*tha 1 monads haskell applicative maybe
我只是有一个关于应用函子的快速问题,以帮助我掌握它们.这只是我在ghci中应用的东西.
[(+3),((-) 3),(*3)] <*> [4]
[7,-1,12]
这对我来说很有意义.基本申请.但在尝试时:
[(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> [Just 4]
我收到了很多错误.我有点理解为什么; 有两个数据构造函数([]和Maybe),并且该<*>函数仅"剥离"其中一个.我想要帮助我理解的是,haskell正在尝试逐步进行直到失败,以及如何绕过它并将其成功计算到:
[(Just 7),(Just -1),(Just 12)]
您有两个不同的Applicative实例.的确如此
Just (* 3) <*> Just 4 == Just 12
但[]实例只是尝试将第一个列表中的每个"函数" 应用到第二个中的每个值,因此您最终尝试应用
(Just (* 3)) (Just 4)
这是一个错误.
(更准确地说,您的Just值列表只有错误的类型才能充当第一个参数<*>.)
相反,您需要映射<*>第一个列表.
> (<*>) <$> [(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> [Just 4]
[Just 7,Just (-1),Just 12]
(在列表中映射高阶函数是您通常首先获得包装函数列表的方式.例如,
> :t [(+3), ((-) 3), (* 3)]
[(+3), ((-) 3), (* 3)] :: Num a => [a -> a]
> :t Just <$> [(+3), ((-) 3), (* 3)]
Just <$> [(+3), ((-) 3), (* 3)] :: Num a => [Maybe (a -> a)]
)
Data.Functor.Compose 评论中提到的另一种选择.
> import Data.Functor.Compose
> :t Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))]
Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))]
  :: Num a => Compose [] Maybe (a -> a)
> Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> Compose [Just 4]
Compose [Just 12,Just (-1),Just 12]
> getCompose <$> Compose [(Just (+3)),(Just ((-) 3)),(Just (*3))] <*> Compose [Just 4]
[Just 12,Just (-1),Just 12]
定义Compose很简单:
newtype Compose f g a = Compose { getCompose: f (g a) }
神奇的是,只要f和g都(应用性)的仿函数,然后Compose f g是又一个(应用性)仿函数.
instance (Functor f, Functor g) => Functor (Compose f g) where
    fmap f (Compose x) = Compose (fmap (fmap f) x)
instance (Applicative f, Applicative g) => Applicative (Compose f g) where
    pure x = Compose (pure (pure x))
    Compose f <*> Compose x = Compose ((<*>) <$> f <*> x)
在Applicative实例中,您可以看到与(<*>) <$> ...上面使用的相同的用法.