我可以编写纯函数:
let f x = x + 1
let g x = x + 2
let z = f . g
z 1 == 4
我似乎也能够组成monadic函数:
let f x = Just (x + 1)
let g x = Just (x + 2)
let z x = f x >>= g
z 1 == Just 4
我认为我应该能够将上一个示例中的f
和g
视为应用并将其组合起来,但不确定如何:
let f x = Just (x + 1)
let g x = Just (x + 2)
let z x = f <*> g -- this doesn't work
z 1 == Just 4
这可行吗?
奖励积分,z x = f x >>= g
可以写成无点功能吗?像z = f >>= g
?
答案 0 :(得分:6)
{-# LANGUAGE TypeOperators #-}
任何两个应用函子的(类型级)组合,
newtype (f :. g) a = Compose { getCompose :: f (g a)) }
instance (Functor f, Functor g) => Functor (f :. g) where
fmap f = Compose . fmap (fmap f) . getCompose
instance (Applicative f, Applicative g) => Applicative (f :. g) where
pure = Compose . pure . pure
Compose fgf <*> Compose fgx = Compose ((<*>) <$> fgf <*> fgx)
您的示例是the Maybe
applicative与the "function" or "reader" applicative (->) r
的组合。
type ReaderWithMaybe r = ((->) r) :. Maybe
x, y :: ReaderWithMaybe Int Int
x = Compose $ \x -> Just (x + 1)
y = Compose $ \x -> Just (x + 2)
由于ReaderWithMaybe r
是Applicative
,您可以执行所有常规Applicative
内容。在这里,我与+
一起粉碎了我的两个价值观。
ghci> let z = (+) <$> x <*> y
ghci> getCompose z 3
Just 9 -- (3 + 1) + (3 + 2) == 9
请注意,x
和y
都会获得相同的输入 3
。这就是(->) r
的{{1}}实例的行为。如果你想取Applicative
的结果并将其输入f x = Just (x + 1)
(以获得与g x = Just (x + 2)
相当的东西),那就是{{1}是为了。
奖励积分,
这样的东西h x = Just (x + 3)
可以写成无点功能吗?像Monad
?
您可以手动轻松定义Kleisli成分。
z x = f x >>= g
标准库中已存在z = f >>= g
及其姐妹(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
f >=> g = \x -> f x >>= g
。他们被称为“鱼”操作员,他们住在Control.Monad
。
答案 1 :(得分:2)
应用功能不是
let f x = Just $ x + 1
let g x = Just $ x + 2
,他们是
let f = Just $ \x -> x + 1
let g = Just $ \x -> x + 2
。然后,合成就像liftA2 (.) f g
或(.) <$> f <*> g
一样。
答案 2 :(得分:0)
也许你会对Kleisli monad的成分感兴趣:
(<=<) :: Monad m => (b -> m c) -> (a -> m b) -> a -> m c
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c