簡體   English   中英

理解一元函數組合

[英]Understanding monadic function composition

我正在從“Learn You a Haskell for Great Good!”一書中學習 monads。 通過米蘭利波瓦卡。 我試圖理解 monad 的結合律。 本質上,法律規定,當您擁有一串帶有>>=的單子函數應用程序時,它們的嵌套方式無關緊要。

以下代碼可以將a -> mb類型的函數的結果傳遞給b -> mc類型的函數:

(<=<) :: (Monad m) => (b -> m c) -> (a -> m b) -> (a -> m c)
f <=< g = (\x -> g x >>= f)

但是,對於下面的示例:

ghci> let f x = [x, -x]
ghci> let g x = [x*3, x*2]
ghci> let h = f <=< g
ghci> h 3
[9, -9, 6, -6]

fxgx都是函數嗎? 似乎它們是具有不同 x 值而不是函數的列表。 在上面的代碼中,這行let h = f <=< g工作的? fg必須是函數,因為它們與<=<一起使用,但我不確定它們是什么。

f x = [x, -x]

這是普通的函數定義語法。 我們正在定義一個新函數f ,寫下它應用於假設值x時會產生什么。

let (無論是作為語句還是let ... in ...表達式)只是引入了一個可以進行定義的塊,就像where一樣。 定義本身使用與全局定義相同的語法。

如果您知道如何通過在文件中編寫例如plusOne n = n + 1來定義函數,那么此語法是完全相同的(如果您不知道該怎么做,那么我建議您閱讀一些介紹性教程在嘗試理解 monadic 函數組合之前,請先了解基本的 Haskell 語法)。

所以在這些定義之后fg是函數。 fxgx沒有真正意義,因為您沒有將它們應用到的x范圍。

如果您在范圍內確實有這樣的值,那么fx將是一個計算結果為列表的表達式,其中涉及調用函數f fxgx是函數仍然是不正確的。

所以現在應該清楚let h = f <=< g通過將<=<運算符應用於fg來定義一個新值h

沒有什么比在一張紙上手工完成定義更能獲得理解的感覺了。

fx = [x, -x]也可以寫成f = (\\ x -> [x, -x]) 因此

  h 3 
= {- by def of h -}
  (f <=< g) 3 
= {- by def of (<=<) -}
  (\x -> g                   x >>= f               ) 3
= {- by defs of f and g -}
  (\x -> (\ x -> [x*3, x*2]) x >>= (\ x -> [x, -x])) 3
= {- by substitution -}
         (\ x -> [x*3, x*2]) 3 >>= (\ x -> [x, -x])
= {- by substitution -}
                 [3*3, 
                  3*2]         >>= (\ x -> [x, -x])
= {- by definition of (>>=) for [] -}
  concat [       (3*3)         &   (\ x -> [x, -x])  -- x & f == f x
         ,       (3*2)         &   (\ x -> [x, -x]) 
         ]
= {- by definition of concat -}
                 (3*3)         &   (\ x -> [x, -x])
         ++      (3*2)         &   (\ x -> [x, -x]) 
= 
  [9, -9, 6, -6]

編輯)有關圖片以及對這些Kleisli 箭頭及其可組合性的更多討論,請參閱我的這個較舊的答案

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM