[Haskell] State Monad

1. 類型

類型用來(lái)區(qū)分內(nèi)存中對(duì)程序員來(lái)說(shuō)不同種類的數(shù)據(jù)塊
而內(nèi)存中存儲(chǔ)的是表達(dá)式的值
所以厂庇,區(qū)分內(nèi)存塊的類型觉啊,就是區(qū)分表達(dá)式的類型

靜態(tài)類型嘉抒,指的是在編譯時(shí)就能確定表達(dá)式的類型
動(dòng)態(tài)類型姿鸿,指的是在運(yùn)行時(shí)才能確定表達(dá)式的類型

注:
靜態(tài)類型殖卑,也可以說(shuō)站削,通過(guò)代碼文本就能確定表達(dá)式的類型

強(qiáng)類型和弱類型是相對(duì)而言的
類型系統(tǒng)的強(qiáng)度指的是,在多大程度上能把表達(dá)式看做是合法類型的
類型強(qiáng)度的表現(xiàn)形式是孵稽,是否允許隱式類型轉(zhuǎn)換
弱類型许起,更允許隱式類型轉(zhuǎn)換
強(qiáng)類型,更不允許隱式類型轉(zhuǎn)換

2. 定義類型

Haskell中定義類型的方式有以下幾種

(1)使用type定義類型別名

type MyTuple = (Int, String)

定義MyTuple為元組類型(Int, String)的別名

(2)使用data定義新類型

data BookType = BookValue Int String

其中菩鲜,BookType是類型名园细,又稱為類型構(gòu)造器,BookValue稱為值構(gòu)造器

一個(gè)BookType類型值接校,可以這樣定義

let bookValue = BookValue 12 "ab"

注:
因?yàn)轭愋蜆?gòu)造器和值構(gòu)造器會(huì)在不同上下文中使用猛频,所以經(jīng)常把它們寫為同一個(gè)名字

data Book = Book Int String

遇到名字Book時(shí)要小心區(qū)分

(3)使用newtype為已有類型定義新的標(biāo)識(shí)
newtype定義的類型狮崩,只能有一個(gè)值構(gòu)造器,且值構(gòu)造器只能有一個(gè)字段

例如:
一個(gè)值構(gòu)造器鹿寻,值構(gòu)造器只有一個(gè)字段睦柴,可以

newtype Okay = ExactlyOne Int

類型構(gòu)造器有多個(gè)參數(shù),但是只有一個(gè)值構(gòu)造器毡熏,值構(gòu)造器只有一個(gè)字段坦敌,也可以

newtype Param a b = Param (Either a b)

字段訪問器語(yǔ)法,可以

newtype Record = Record {
    getInt :: Int
}

注:
字段訪問器語(yǔ)法痢法,同時(shí)定義了字段的類型Int狱窘,以及字段的訪問器函數(shù)getInt :: Record -> Int
例如:
通過(guò)值構(gòu)造器Record構(gòu)造該類型的值,Record 12
通過(guò)訪問器提取字段的值疯暑,getInt (Record 12)

有一個(gè)值構(gòu)造器训柴,但是值構(gòu)造器沒有字段,不可以

newtype TooFew = TooFew

有一個(gè)值構(gòu)造器妇拯,但是值構(gòu)造器有兩個(gè)字段幻馁,不可以

newtype TooManyFields = Fields Int Int

有多個(gè)值構(gòu)造器,不可以

newtype TooManyCtors = Bad Int
    | Worse Int

3. 帶參數(shù)的類型

類型構(gòu)造器也可以帶參數(shù)

data Maybe a = Nothing
   | Just a

data Either a b = Left a
    | Right b

其中越锈,Maybe是類型構(gòu)造器仗嗦,Maybe Int才是一個(gè)具體的類型
Either是類型構(gòu)造器,Either Int String才是一個(gè)具體的類型

注:
與函數(shù)的Currying相似甘凭,類型構(gòu)造器也可以Currying
Either是一個(gè)類型構(gòu)造器稀拐,提供兩個(gè)類型IntString,得到類型Either Int String
Either Int也是一個(gè)類型構(gòu)造器丹弱,提供類型String德撬,得到類型Either Int String

4. newtype

使用newtype為已有類型定義編譯時(shí)的新標(biāo)識(shí),
這個(gè)標(biāo)識(shí)在運(yùn)行時(shí)會(huì)轉(zhuǎn)換為原有的類型躲胳,可以稱為去殼

例如:
定義新的類型

data DataInt = D Int
    deriving (Eq, Ord, Show)

定義編譯時(shí)的類型外殼

newtype NewtypeInt = N Int
    deriving (Eq, Ord, Show)

運(yùn)行時(shí)蜓洪,求值undefined會(huì)發(fā)生錯(cuò)誤

ghci> undefined
*** Exception: Prelude.undefined

運(yùn)行時(shí),_可以匹配所有坯苹,undefined不求值

ghci> case D undefined of D _ -> 1
1

運(yùn)行時(shí)隆檀,N外殼會(huì)去掉,即case undefined of _ -> 1粹湃,_可以匹配所有恐仑,undefined不求值

ghci> case N undefined of N _ -> 1
1

運(yùn)行時(shí),D _來(lái)匹配undefined的求值結(jié)果为鳄,undefined要求值裳仆,發(fā)生錯(cuò)誤

ghci> case undefined of D _ -> 1
*** Exception: Prelude.undefined

運(yùn)行時(shí),N外殼會(huì)去掉孤钦,即case undefined of _ -> 1歧斟,_可以匹配所有记某,undefined不求值

ghci> case undefined of N _ -> 1
1

5. typeclass

類型類提取了相似的運(yùn)算
類型類的實(shí)例是一個(gè)類型構(gòu)造器,這個(gè)類型構(gòu)造器構(gòu)造的類型具有類型類指定的運(yùn)算

注:
類型類的實(shí)例构捡,是一個(gè)類型構(gòu)造器
類型構(gòu)造器液南,可以是零元類型構(gòu)造器(具體的類型),也可以帶參數(shù)

例如:

class BasicEq a where
    isEqual :: a -> a -> Bool

其中勾徽,BasicEq類型類滑凉,定義了isEqual函數(shù)

指定類型構(gòu)造器Bool(零元類型構(gòu)造器,即具體的類型)是BasicEq類型類的實(shí)例
于是喘帚,isEqual就具體化為isEqual :: Bool -> Bool -> Bool

instance BasicEq Bool where
    isEqual True  True  = True
    isEqual False False = True
    isEqual _     _     = False

6. Monad

Monad是一個(gè)類型類
針對(duì)一般化的鏈?zhǔn)讲僮鞒╂ⅲx了>>=return兩種運(yùn)算

class Monad m where
    -- chain
    (>>=)  :: m a -> (a -> m b) -> m b
    -- inject
    return :: a -> m a

其中,Monad類型類的實(shí)例吹由,是一個(gè)單參類型構(gòu)造器

注:
m a類型的值若未,通常稱之為action
有時(shí)候,返回action的函數(shù)倾鲫,也稱之為action

instance Monad Maybe where
    Nothing >>= f = Nothing
    Just a >>= f = f a
    return = Just

其中粗合,>>=具體化為了(>>=) :: Maybe a -> (a -> Maybe b) -> Maybe b
return具體化為了return :: a -> Maybe a
f的類型是f :: a -> Maybe b
NothingJustMaybe a類型的值構(gòu)造器

data Maybe a = Nothing
    | Just a

注:
Monad還定義了兩種操作>>fail

(>>) :: m a -> m b -> m b
a >> f = a >>= \_ -> f

>>并不關(guān)心a的執(zhí)行結(jié)果,只是進(jìn)行順序調(diào)用

fail :: String -> m a
fail = error

7. do語(yǔ)法塊

do語(yǔ)法塊會(huì)在編譯時(shí)轉(zhuǎn)換為>>=乌昔,>>return形式

(1)單個(gè)action

doNotation1 =
    do act

translated1 =
    act

(2)多個(gè)action

doNotation2 =
    do act1
       act2
       {- ... etc. -}
       actN

translated2 =
    act1 >>
    do act2
       {- ... etc. -}
       actN

finalTranslation2 =
    act1 >>
    act2 >>
    {- ... etc. -}
    actN

(3)帶有<-的action

doNotation3 =
    do pattern <- act1
       act2
       {- ... etc. -}
       actN

translated3 =
    let f pattern = do act2
                       {- ... etc. -}
                       actN
        f _ = fail "..."
    in act1 >>= f

(4)let

doNotation4 =
    do let val1 = expr1
           val2 = expr2
           {- ... etc. -}
           valN = exprN
       act1
       act2
       {- ... etc. -}
       actN

translated4 =
    let val1 = expr1
        val2 = expr2
        valN = exprN
    in do act1
          act2
          {- ... etc. -}
          actN

8. State Monad

為原有類型定義一個(gè)新的標(biāo)識(shí)

newtype State s a = State {
        runState :: s -> (a, s)
    }

其中隙疚,類型構(gòu)造器是State
字段的類型是s->(a,s)是一個(gè)函數(shù)
字段訪問器是runState

注:
因?yàn)?code>State是一個(gè)雙參類型構(gòu)造器,
所以State s是一個(gè)單參類型構(gòu)造器
runState的類型是runState :: State s a -> s -> (a, s)

指定State s是Monad類型類的實(shí)例

instance Monad (State s) where
...

注:
Monad類型類的實(shí)例磕道,是一個(gè)單參類型構(gòu)造器供屉,
所以,State s是Monad類型類的實(shí)例溺蕉,State不是

returnState :: a -> State s a
returnState a = State $ \s -> (a, s)

bindState :: State s a -> (a -> State s b) -> State s b
bindState m k = State $ \s -> let (a, s') = runState m s
                                                    in runState (k a) s'

其中伶丐,m的類型是m :: State s a
k的類型是k :: a -> State s b
runState的類型是runState :: State s a -> s -> (a, s)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市疯特,隨后出現(xiàn)的幾起案子哗魂,更是在濱河造成了極大的恐慌,老刑警劉巖辙芍,帶你破解...
    沈念sama閱讀 212,454評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件啡彬,死亡現(xiàn)場(chǎng)離奇詭異羹与,居然都是意外死亡故硅,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,553評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門纵搁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)吃衅,“玉大人,你說(shuō)我怎么就攤上這事腾誉∨遣悖” “怎么了峻呕?”我有些...
    開封第一講書人閱讀 157,921評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)趣效。 經(jīng)常有香客問我瘦癌,道長(zhǎng),這世上最難降的妖魔是什么跷敬? 我笑而不...
    開封第一講書人閱讀 56,648評(píng)論 1 284
  • 正文 為了忘掉前任讯私,我火速辦了婚禮,結(jié)果婚禮上西傀,老公的妹妹穿的比我還像新娘斤寇。我一直安慰自己,他們只是感情好拥褂,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,770評(píng)論 6 386
  • 文/花漫 我一把揭開白布娘锁。 她就那樣靜靜地躺著,像睡著了一般饺鹃。 火紅的嫁衣襯著肌膚如雪莫秆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,950評(píng)論 1 291
  • 那天悔详,我揣著相機(jī)與錄音馏锡,去河邊找鬼。 笑死伟端,一個(gè)胖子當(dāng)著我的面吹牛杯道,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播责蝠,決...
    沈念sama閱讀 39,090評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼党巾,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了霜医?” 一聲冷哼從身側(cè)響起齿拂,我...
    開封第一講書人閱讀 37,817評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎肴敛,沒想到半個(gè)月后署海,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,275評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡医男,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,592評(píng)論 2 327
  • 正文 我和宋清朗相戀三年砸狞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片镀梭。...
    茶點(diǎn)故事閱讀 38,724評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡刀森,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出报账,到底是詐尸還是另有隱情研底,我是刑警寧澤埠偿,帶...
    沈念sama閱讀 34,409評(píng)論 4 333
  • 正文 年R本政府宣布,位于F島的核電站榜晦,受9級(jí)特大地震影響冠蒋,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜乾胶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,052評(píng)論 3 316
  • 文/蒙蒙 一浊服、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧胚吁,春花似錦牙躺、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,815評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至半抱,卻和暖如春脓恕,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背窿侈。 一陣腳步聲響...
    開封第一講書人閱讀 32,043評(píng)論 1 266
  • 我被黑心中介騙來(lái)泰國(guó)打工炼幔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人史简。 一個(gè)月前我還...
    沈念sama閱讀 46,503評(píng)論 2 361
  • 正文 我出身青樓乃秀,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親圆兵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子跺讯,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,627評(píng)論 2 350

推薦閱讀更多精彩內(nèi)容

  • 初識(shí)狀態(tài) 先看一個(gè)小游戲,這個(gè)小游戲用字符串來(lái)控制殉农,最后得到總分刀脏。c用來(lái)啟動(dòng)和停止計(jì)分,在啟動(dòng)計(jì)分狀態(tài)下a加一分超凳,...
    何幻閱讀 1,012評(píng)論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理愈污,服務(wù)發(fā)現(xiàn),斷路器轮傍,智...
    卡卡羅2017閱讀 134,637評(píng)論 18 139
  • 本文為翻譯暂雹,個(gè)人學(xué)習(xí)之用,原地址 程序狀態(tài) 如果你以前有其他語(yǔ)言的編程經(jīng)驗(yàn)金麸,你可能寫過(guò)一些函數(shù)或者方法來(lái)控制程序的...
    ParkinWu閱讀 3,020評(píng)論 0 3
  • 前言 近期又開始折騰起Haskell擎析,掉進(jìn)這個(gè)深坑恐怕很難再爬上來(lái)了簿盅。在不斷深入了解Haskell的各種概念以及使...
    Tangentw閱讀 2,139評(píng)論 0 9
  • 驕陽(yáng)如火 殘暴的炙烤著大地 悶熱的天 壓抑的讓人透不過(guò)氣來(lái) 獨(dú)坐窗前 思緒萬(wàn)千 一路走來(lái) 肩上的行囊空空如...
    不在彼岸只在海閱讀 217評(píng)論 2 2