Home >> Blog >> monad 單子理論導論

又到了放下手中SEO優化工作讓大腦短暫進入到軟體工程師的進修殿堂的時候了。

monad 單子理論導論

單子理論導論

什麼是單子?

  • monad 是范疇論中的代數結構,在 Haskell 中,它用於將計算描述為步驟序列,並用於處理狀態和 IO 等副作用。
  • Monad 是抽象的,它們有許多有用的具體實例。
  • Monad 提供了一種構建程序的方法。
  • 它們可以(與抽像數據類型一起)用於允許安全地實現操作(例如可變變量)。

單子的構建塊

monad 具有三個構建塊:

  • 給定計算結果的類型,生成計算類型的類型構造函數。
  • 一個函數,它接受一個值,並返回一個計算——當執行時——將產生那個值。
  • 一個函數,它接受兩個計算並一個接一個地執行它們,使第一個計算的結果可用於第二個計算。

讓我們更準確地重申這一點:

單子的定義

一個單子由三個對象組成,它們必須滿足單子定律。我們先來看看對象:

  • 類型構造函數 (M),對於任何類型 (a),類型 (M a) 是生成類型 (a) 的結果的單子 (M) 中的計算類型。
  • 一個函數(return :: a rightarrow M, a)。因此,如果 (x::a),則 (return , x) 是 (M) 中的計算,執行時將產生類型 (a) 的值。
  • 一個函數 ((>>=) :: M, a rightarrow (a rightarrow M, b) rightarrow M, b)。

  • 第一個參數是產生類型 (a) 的值的計算。
  • 第二個參數是一個函數,它需要一個類型為 (a) 的參數並返回一個產生類型 (b) 的值的計算。
  • 結果是一個將產生類型 (b) 的值的計算。它通過運行第一個計算並將其結果傳遞給返回第二個計算的函數來工作,然後執行該計算。

Monad 和 Type 類

  • 單子是抽象的、通用的和有用的。
  • 因此,它們的例子很多。
  • 這是通過為 monad 定義一個類型類以及許多標準實例來捕獲的。你可以定義你自己的。

Monad類型類

class Monad m where
return :: a -> m a
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
fail :: String -> m a

  • 該return函數接受一個值並返回一個單子值,即包裝在單子類型構造函數中的值。
  • 操作符(讀作“ >>=bind”)是 monad 的關鍵部分。它將一個計算返回的值綁定到另一個計算。
  • 有時計算返回的值並不重要。
  • 運算符(讀作“ >>then”)類似於>>=,但它只是忽略了計算返回的值:

    m >> n = m >>= _ -> n

  • 當模式不匹配時,系統使用該fail函數幫助生成錯誤消息;通常你不會直接使用它。
  • 我們就假裝fail不在那裡。

單子定律

每個單子必須滿足以下三個定律。因此,如果某個東西看起來像 monad 但不滿足這些定律,那麼它就不是 monad!定律表達了為了使一元計算可組合而需要滿足的屬性。

  • 權利單位法:

    m >>= return = m

  • 左單位法:

    return x >>= f = f x

  • 結合律:

    (m >>= f) >>= g = m >>= (x -> f x >>= g)

monad 就是定義所說的那樣!

  • 關於什麼是單子有很多隱喻或直覺。
  • 例如:“計算”或“動作”。
  • 但這些術語含糊不清——它們可能會幫助您理解,但有時也會產生誤導。
  • monad 正是定義所說的,不多也不少。

do符號_

使用 bind 和 then 運算符編寫一元計算仍然有些笨拙。Haskell 為一元計算提供了一種非常方便的語法,稱為“do notation”:

baz :: [a] -> Maybe a

baz xs =
do a myTail xs
b myTail a
c myHead b
return c

do 的語法規則

do { x } -- > x

do {x ; xs> } -- > x >> do { }

do { a x ; xs> } -- > x >>= a -> do { }

do { let declarations> ; xs }
-- >
let declarations> in do { xs }