Haskell语言学习笔记(13)Monadic Functions

Monadic Functions

liftM

Monad 的 liftM 相当于 Functor 的 fmap。
liftM :: (Monad m) => (a1 -> r) -> m a1 -> m r
liftM f m1 = do { x1 <- m1; return (f x1) }
Prelude Control.Monad> liftM (*3) (Just 8)
Just 24
Prelude Control.Monad> liftM (*3) [1,2,3]
[3,6,9]
Prelude Control.Monad> putStr "Write your string: " >> liftM (map Data.Char.toUpper) getLine >>= putStrLn
Write your string: This is my string!
THIS IS MY STRING!

ap

Monad 的 ap 相当于 Applicative Functor 的 <*>。
ap :: (Monad m) => m (a -> b) -> m a -> m b
ap m1 m2 = do { x1 <- m1; x2 <- m2; return (x1 x2) }
Prelude Control.Monad> ap (Just (*3)) (Just 8)
Just 24
Prelude Control.Monad> ap [(*3),(+3)] [1,2,3]
[3,6,9,4,5,6]

liftM2 liftM3 liftM4 liftM5

Monad 的 liftM2 相当于 Applicative Functor 的 liftA2。
liftM2 :: (Monad m) => (a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 f m1 m2 = do { x1 <- m1; x2 <- m2; return (f x1 x2) }
liftM3 :: (Monad m) => (a1 -> a2 -> a3 -> r) -> m a1 -> m a2 -> m a3 -> m r
liftM3 f m1 m2 m3 = do { x1 <- m1; x2 <- m2; x3 <- m3; return (f x1 x2 x3) }
Prelude Control.Monad> liftM2 (*) (Just 3) (Just 8)
Just 24
Prelude Control.Monad> liftM2 (*) [1,2,3] [4,5,6]
[4,5,6,8,10,12,12,15,18]

join

join 函数移除一层 Monadic structure, 使其平坦化。
join :: (Monad m) => m (m a) -> m a
join x = x >>= id
Prelude Control.Monad> join (Just (Just 9))
Just 9
Prelude Control.Monad> join [[1,2,3],[4,5,6]]
[1,2,3,4,5,6]

filterM

filterM 是列表操作函数 filter 的一般化。
filterM :: (Applicative m) => (a -> m Bool) -> [a] -> m [a]
import Control.Monad
import Control.Monad.Trans.Writer

keepSmall :: Int -> Writer [String] Bool
keepSmall x
    | x < 4 = do
        tell ["Keeping " ++ show x]
        return True
    | otherwise = do
        tell [show x ++ " is too large, throwing it away"]
        return False
main = do
    let (a, w) = runWriter $ filterM keepSmall [9,1,5,2,10,3]
    mapM_ putStrLn w; print a

{-
9 is too large, throwing it away
Keeping 1
5 is too large, throwing it away
Keeping 2
10 is too large, throwing it away
Keeping 3
[1,2,3]
-}
Prelude Control.Monad> filterM (\x -> [False, True]) [1,2,3]
[[],[3],[2],[2,3],[1],[1,3],[1,2],[1,2,3]]

foldM

foldM 是列表操作函数 foldl 的一般化。
foldM :: (Foldable t, Monad m) => (b -> a -> m b) -> b -> t a -> m b
Prelude Control.Monad> let binSmalls acc x = if x > 9 then Nothing else Just (acc + x)
Prelude Control.Monad> foldM binSmalls 0 [2,8,3,1]
Just 14
Prelude Control.Monad> foldM binSmalls 0 [2,11,3,1]
Nothing

replicateM replicateM_

replicate 函数所对应的 monadic 版本。
replicateM        :: (Applicative m) => Int -> m a -> m [a]
replicateM cnt0 f =
    loop cnt0
  where
    loop cnt
        | cnt <= 0  = pure []
        | otherwise = liftA2 (:) f (loop (cnt - 1))
Prelude Control.Monad> replicateM 3 getLine
1
2
3
["1","2","3"]

when unless

when函数:给定一个布尔值和一个IO Action,如果布尔值为真,就执行IO Action,否则返回空。
unless函数:给定一个布尔值和一个IO Action,如果布尔值为假,就执行IO Action,否则返回空。
when :: (Applicative f) => Bool -> f () -> f ()
when p s  = if p then s else pure ()
unless :: (Applicative f) => Bool -> f () -> f ()
unless p s = if p then pure () else s
Prelude> let debug = True
Prelude Control.Monad> when debug $ print "Debugging"
"Debugging"
Prelude Control.Monad> unless debug $ print "Debugging"
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值