haskell的世界观(2)


一个Monad m定义了一个运算(computation):
图中上面一个是monad m a,下面一个是function (a->mb)。
可以大致这么理解,一个monad是包含两面的,它除了在一个世界中作为a以外,还携带了另外一个世界如何从in变化到out的信息。所以,一个monad还叫做action,或者computation。例如,IO monad又称IO action。后面为了不用每次画图,我们这样画一个monad:
a//in->out,或者a//in,或者a//out
而a->m b这样画:
a->b//in->out
 
 
Monad有四个基本运算分别是:bind(>>=), then(>>), return, fail。
 
 
从数学的角度讲,一个monad只需要两个运算,>>=和return就够了。不过从程序设计角度,为了便利,添加了>>和fail,他们分别是>>=和return的特化型。
 
bind运算把一个monad m a的pure部分取出来,放到一个monad constructor (a->m b)中,构造器产生一个新的monad m b,借此把a输送给real world。
then运算是特殊的bind,它描述了两个monad的顺序诞生。
return运算是一个特殊的constructor,它接受一个pure world中的a,产生一个monad m a。
fail运算是特殊的return,它接受一个String之后,产生一个monad,同时把这个String输送给real world。
 
monad三定律:
(1) return a >>= k  ==  k a
(2) m >>= return  ==  m
(3) m >>= (/x -> k x >>= h)  ==  (m >>= k) >>= h
 
第一个,monad bind到constructor等价于直接apply monad中的pure部分到constructor。
第二个,return保留monad的所有信息不变。
第三个,bind运算满足结合律。
 
好了,看了这么些难以理解的概念之后,让我们看看几个实际的例子吧。
 
1. putStrLn :: String -> IO ()
putStrLn函数根据pure world中的一个String构造了一个IO monad IO ()。
 
2. Just :: a -> Maybe a
Just这个constructor根据a构造一个Maybe monad Maybe a。
试试把一个Maybe monad bind到print看看:
Prelude> (Just 3)>>=print
    Couldn't match expected type `Maybe' against inferred type `IO'
      Expected type: t -> Maybe b
      Inferred type: t -> IO ()
看起来,monad只能bind到能够构造同类型monad的constructor上。
Prelude> let f x | x>=0 = Just (x+1) | x<0 = Nothing
Prelude> :t f
f :: (Ord a, Num a) => a -> Maybe a
Prelude> (Just 3)>>=f
Just 4
Prelude> (Just (-1))>>=f
Nothing
进一步看看:
Prelude> :t f 3
f 3 :: (Ord t, Num t) => Maybe t
Prelude> :t f (-1)
f (-1) :: (Ord a, Num a) => Maybe a
可以看到,real world中不是只有I/O一种action。
 
3. rollDice = getStdRandom (randomR (1,6)) :: IO Integer
这是一个随机数产生函数。
试试看:
Prelude> :m System.Random
Prelude System.Random> let rollDice = getStdRandom(randomR(1,6))
Prelude System.Random> mapM (/x->rollDice) [1..12]
[3,5,3,6,2,4,5,1,5,6,3,2]
 
 
st.monad@gmail.com原创,转贴请注明出处,谢谢!
 
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值