haskell monad

Monad 是一个从 Applicative functors 很自然的一个演进结果。对于他们我们主要考量的点是:如果你有一个具有 context 的值 m a,你能如何把他丢进一个只接受普通值 a 的函数中,并回传一个具有 context 的值?也就是说,你如何套用一个型态为 a -> m b 的函数至 m a?基本上,我们要求的函数是:

(>>=:: (Monad m) => m a -> (a -> m b) -> m b

如果我们有一个漂亮的值跟一个函数接受普通的值但回传漂亮的值,那我们要如何要把漂亮的值丢进函数中?这就是我们使用 Monad 时所要考量的事情。我们不写成 f a 而写成 m a 是因为 m 代表的是 Monad,但 monad 不过就是支持 >>= 操作的 applicative functors。>>= 我们称呼他为 bind。

当我们有一个普通值 a 跟一个普通函数 a -> b,要套用函数是一件很简单的事。但当你在处理具有 context 的值时,就需要多考虑些东西,要如何把漂亮的值喂进函数中,并如何考虑他们的行为,但你将会了解到他们其实不难。


class Monad m where   
    return :: a -> m a   
 
    (>>=:: m a -> (a -> m b) -> m b   
 
    (>>:: m a -> m b -> m b   
    x >> y = x >>= \_ -> y   
 
    fail :: String -> m a   
    fail msg = error msg
return  等价于  pure. 型态是 (Monad m) => a -> m a. 
并不是结束一个函数的执行,他只不过是把一个普通值包进一个 context 里面。

   bind: >>=。他就像是函数套用一样,只差在他不接受普通值,他是接受一个 monadic value(也就是具有 context 的值)
并且把他喂给一个接受普通值的函数,并回传一个 monadic value。

instance Monad Maybe where   
    return x = Just x   
    Nothing >>= f = Nothing   
    Just x >>= f  = f x   
    fail _ = Nothing
instance Monad [] where   
    return x = [x]   
    xs >>= f = concat (map f xs)   
    fail _ = []
ghci> [3,4,5>>= \x -> [x,-x]   
[3,-3,4,-4,5,-5]
class Monad m => MonadPlus m where   
    mzero :: m a   
    mplus :: m a -> m a -> m a
instance MonadPlus [] where   
    mzero = []   
    mplus = (++)
MonadPlus 和 Monoid 很像

guard :: (MonadPlus m) => Bool -> m ()   
guard True = return ()   
guard False = mzero
ghci> guard (5 > 2:: Maybe ()   
Just ()   
ghci> guard (1 > 2:: Maybe ()   
Nothing   
ghci> guard (5 > 2:: [()]   
[()]   
ghci> guard (1 > 2:: [()]   
[]
ghci> guard (5 > 2>> return "cool" :: [String]   
["cool"]   
ghci> guard (1 > 2>> return "cool" :: [String]   
[]

Monad laws (单子律)

  retrun x >>= f  应该等于  f x ( Left identity 

m >>= return 会等于 m (Right identity)

 * (m >>= f) >>= g 跟 m >>= (\x -> f x >>= g) 是相等的 (Associativity)

(.) :: (b -> c) -> (a -> b) -> (a -> c)   
f . g = (\x -> f (g x))

如果 g 的型态是 a -> b 且 f 的型态是 b -> c,我们可以把他们合成一个型态是 a -> c 的新函数。
所以中间的参数都有自动带过。现在假设这两个函数是 monadic function,也就是说如果他们的回传值是 monadic function?
如果我们有一个函数他的型态是 a -> m b,我们并不能直接把结果丢给另一个型态为 b -> m c 的函数,
因为后者只接受型态为 b 的普通值。然而,我们可以用 >>= 来做到我们想要的事。有了 >>=
我们可以合成两个 monadic function:

(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)   
<=< g = (\x -> g x >>= f)

合成的定律:f <=< (g <=< h) 跟(f <=< g) <=< h 应该等价

do 表示法


foo :: Maybe String   
foo = Just 3   >>= (\x ->  
      Just "!" >>= (\y ->  
      Just (show x ++ y)))
foo :: Maybe String   
foo = do   
    x <- Just 3   
    y <- Just "!"   
    Just (show x ++ y)
如果我们拿到一个 Maybe String ,并用  <-  来绑定给一个变量,那个变量就会是一个  String



 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值