在Haskell中实现liftM2

jus*_*ker 3 haskell functional-programming

对于练习,我一直在尝试使用函数ap和liftM来实现liftM2.功能定义为:

ap :: IO (a -> b) -> IO a -> IO b
liftM :: (a -> b) -> IO a -> IO b

liftM2 :: (a -> b -> c) -> IO a -> IO b -> IO c
Run Code Online (Sandbox Code Playgroud)

我可以使用do notation轻松做liftM2,但不知道如何使用ap和liftM来做到这一点.我想将结果看起来像这样:

liftM2 f a b = liftM (_) (ap _ a)
Run Code Online (Sandbox Code Playgroud)

我很困惑如何弄乱f,这是(a - > b - > c),这样我就可以将a转为b,b转为c.谢谢.

chi*_*chi 6

一般模式正在转变

liftMn f a1 ... an
Run Code Online (Sandbox Code Playgroud)

f <$> a1 <*> ... <*> an
-- i.e., more precisely
(... ((f <$> a1) <*> a2) ... <*> an)
Run Code Online (Sandbox Code Playgroud)

其中<$>liftM(AKA fmap)和<*>ap.

因此,n=2我们得到了

(f `liftM` a1) `ap` a2
-- i.e.
ap (liftM f a1) a2
Run Code Online (Sandbox Code Playgroud)

检查类型:

f :: t1 -> t2 -> r
liftM f :: IO t1 -> IO (t2 -> r)
a1 :: IO t1
liftM f a1 :: IO (t2 -> r)
ap (liftM f a1) :: IO t2 -> IO r
a2 :: IO t2
ap (liftM f a1) a2 :: IO r
Run Code Online (Sandbox Code Playgroud)

这里的关键思想是阅读f :: t1 -> t2 -> rf :: t1 -> (t2 -> r)使liftM f :: IO t1 -> IO (t2 -> r)如下.注意里面的功能类型IO.然后,我们可以在"分配" IO->使用ap,这样我们就可以申请a2 :: IO t2.