Haskell:从Maybe Monad理解Monad

Haskell:从Maybe Monad理解Monad

Monad的原始定义

-- Monad的原始定义
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就是给原始类型套一个构造性类型的壳,比如在Maybereturn x = Just x就是把a包装成Maybe a
failerror实现,很好理解,是为了将报错作为一个副作用进行,从而保证函数在报错的情况下仍然能返回一个类型正确的值。
以下通过Maybe中的Monad实现,解释一下>>=>>为什么设计成这样,在实际使用时有什么效果。

Monads are just applicative functors that support >>=. (The >>= function is pronounced as bind.)

Maybe的Monad实现

-- MaybeMonad instance
instance Monad Maybe where
    return x = Just x
    Nothing >>= f = Nothing
    Just x >>= f  = f x
    fail _ = Nothing

-- 此时
-- Just x >> y = y
-- Nothing >> _ = Nothing

return用来套壳,>>=用来实现连续传值(下面详细讲),fail使Maybe可以用自己的方式(返回Nothing)实现异常处理。

理解>>=

考虑>>=在大部分时间的使用方式:Just 1 >>= fun1 >>= fun2 >>= ... >>= funn,即一个值通过函数求出结果,再把结果作为下一个函数的输入。当我们使用Maybe时,我们肯定希望每一步的值都是用Just包裹的,安全的值。所以,>>=的第一个输入类型是Maybe a,最终输出类型是Maybe b,这一点是很合理的。

主要的问题是,参数f的类型为什么是a -> mb

  • 为什么不是m a -> m b?因为我们希望f的输入值本身在类型上没有问题。a -> mb使得f的输入是一个纯值,这个纯值的安全性由>>=的implement保证。此时,输入类型不允许maybe,就保证输入值是有意义的(不是Nothing)。此时,f只需要处理函数功能上的异常(比如除法div函数不允许输入0),而m a可能存在的异常(Nothing)之前已经由>>=处理了:>>=在解绑Just的时候如果发现异常(Nothing)就会直接停止求值而返回Nothing
  • 为什么不是a -> b?因为我们希望返回值反映f函数内部功能上的异常:针对功能的异常处理是f内部逻辑的一部分。比如除法div函数,0是一个类型正常的输入值,但是不能正确执行除法,所以依托Maybe类型返回Nothing.

在理清>>=的类型为什么设计之后,注意到>>的实现,也能知道>>的目的:在一系列处理值中,一旦有一个失败就返回Nothing

总结

Maybe就是为了表示异常而设立的一种结构,而Monad创立的作用就是减少很多重复的异常处理代码。Maybe Monad把函数连续调用时的异常传递的判断逻辑隔离了出来,从而减少了很多代码量,也能使得设计函数时更注意函数本身的逻辑和安全,而不用过分考虑输出值。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值