2007-04-02舊作。原載:
乙個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
第二個,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]
我的世界觀
我的世界觀 阿爾伯特 愛因斯坦 我們這些總有一死的人的命運多麼奇特!我們每個人在這個世界上都只作乙個短暫的逗留 目的何在,卻無從知道,儘管有時自以為對此若有所感。但是,不必深思,只要從日常生活就可以明白 人是為別人而生存的 首先是為那樣一些人,我們的幸福全部依賴於他們的喜悅和健康 其次是為許多我們所...
佛教的世界觀
所有的哲學首當其衝的命題就是宇宙觀與世界觀。我們身處何地,我們從 來?要到 去?佛教的宇宙觀和世界觀或許不是完全正確的,但卻是開放的 佛教中的乙個世界 就是以日月系統作為乙個世界的單位。1000個這樣的世界是乙個小千世界 1000個小千世界,就是乙個中千世界,1000個中千世界,就是乙個大千世界。佛...
敏捷的世界觀
有一種相當流行的軟體方法學要求對乙個專案分配35種不同的角色,包括架構師 設計人員 編碼人員 文件管理者等。敏捷方法卻背道而馳,只需乙個角色 軟體開發者,也就是你。專案需要什麼你就做什麼,你的任務就是與客戶緊密協作,一起開發軟體。敏捷依賴人,而不是依賴於專案的甘特圖和里程表。這大概是全棧工程師吧,哈...