簡體   English   中英

Reader monad 的“詢問”function 是如何工作的?

[英]How does the Reader monad's "ask" function work?

data T b = E | N b (T b) (T b) 


f :: T b -> Reader Int (T Int)
f (N i l r) = ask >>= \x ->  local ((-)4) (f l) >>= \l' -> local ((-)1) (f r) >>= \r' -> return (N x l' r')
f E = return E

我對理解這段代碼的工作原理有疑問。 特別是, ask如何知道環境在哪里(在我們的例子中只是Int )?

更准確地說:我是一個命令式程序員,使用這種語言很容易。 可以在任何 object 上調用方法,例如: obj.f() ,或者當我們希望 function 使用外部數據時,我們必須通過參數傳遞數據。

這就是Reader monad的功能 它為您提供了一個ask功能,“神奇地”突然彈出一個值。 要實際使用它,您需要調用runReader ,並為其提供Int環境。 然后, Reader類型將其自動從runReader調用傳播到每個ask調用。

簡短的手工波浪形答案。 Reader Int (T Int)值本質上只是Int -> (T Int)類型的包裝函數。 為了運行該功能,我們首先需要提取它。 我們使用runReader做到這runReader

data T b = ... deriving (Show)

main = let tree = (N 10 (N 8 E E) E)
           g = f tree
           h = runReader g
       in print $ h 20

(通常,您只需編寫print $ runReader (f tree) 20 ;我將其拆分為對應下面的粗略類比。)

ask (由MonadReader類型類定義,並由用於定義Reader類型的ReaderT monad轉換Reader )基本上檢索傳遞給h的參數的值。

從某種意義上說, Reader Int (T Int)是一個包含函數g的對象,該函數調用函數ask runReader g創建一個新函數,該函數在被調用時定義一個簡單地返回其參數的ask函數,然后調用g 現在,當g調用ask ,它將返回最初傳遞給h的參數。

我建議先閱讀這篇文章。 問定義:

ask :: (Monad m) => ReaderT r m r
ask = ReaderT return

和讀者:

newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a }
type Reader r = ReaderT r Identity

所以

do
  r <- ask
  ...

相當於

do
  r <- ReaderT return
  ...

所以本質上<-只是進入 identity monad,並獲取最終將被runReader R = return提升的任何價值。

這將啟用 haskell 中的全局變量。

暫無
暫無

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

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