我認爲如果兩個下面的表達式是等價的:功能當地哈斯克爾讀者單子
env <- ask
local (\_ -> env) sth
和:
local (\env -> env) sth
如果不是,它被帶到參數的lambda?
我認爲如果兩個下面的表達式是等價的:功能當地哈斯克爾讀者單子
env <- ask
local (\_ -> env) sth
和:
local (\env -> env) sth
如果不是,它被帶到參數的lambda?
不確定你的問題是關於什麼的,但讓我們試試。
所以你問如果
ask >>= \env -> local (const env) sth
和
local id sth
是等價的。
在效果方面 - 確定它們是。更重要的是,它們相當於sth
。讓我們考慮,這是一個稍微複雜一些的例子:
ask >>= \env -> local (const (f env)) sth
VS
local f sth
現在讓我們試着去了解它是如何工作的。
local
被定義爲
local :: (r -> r) -> Reader r a -> Reader r a
local f m = Reader $ runReader m . f
(我簡化了一下,因爲它是爲ReaderT
通過withReaderT
實際定義,但它得到跨想法)
提醒一下,我們可以假設
runReader :: Reader r a -> r -> a
另外,作爲提醒Reader r a
是一個封裝r -> a
一個NEWTYPE。
現在,>>=
在這裏做什麼?簡單,
m >>= k = Reader $ \r -> runReader (k (runReader m r)) r
因此,它需要m
,從中提取價值,並將它傳遞給k
,同時保持實際環境r
作爲一個自由參數。作爲一個行爲良好的monadic綁定應該,在這裏沒有什麼驚喜。
還承擔指出,這ask
只是Reader id
那麼現在,讓我們完全放棄整個Reader
事情,只是改寫我們的表達式作爲功能。
ask >>= \env -> local (const (f env)) sth
就變成
\r -> (\r' -> runReader sth (const (f r) r')) r
和
local f sth
成爲
\r -> runReader sth (f r)
現在,如果你眯了一下,你可以看到這兩個方面是等價的影響。事實上,
const (f r) r' = f r
(\r' -> runReader sth (f r)) r = (\_ -> runReader sth (f r)) r
= runReader sth (f r)
所以
\r -> (\r' -> runReader sth (const (f r) r')) r
變成
\r -> runReader sth (f r)
這是完全一樣local f sth
。
現在的問題是,您的編譯器是否足夠聰明,可以自行完成這種轉換?如果我不得不猜測,我會猜測GHC 是確實夠聰明,因爲它都是基本的代數平等。但幸運的是,我沒有有來猜測,因爲我可以檢查。
使用這兩種來源,test1.hs
:
import Control.Monad.Reader
main :: IO()
main = print $ runReader m "hello"
f = (++"!!!")
m = ask >>= \r -> local (const (f r)) ask
和test2.hs
:
import Control.Monad.Reader
main :: IO()
main = print $ runReader m "hello"
f = (++"!!!")
m = local f ask
我(GHC使用7.10.3)跑ghc -O2 -ddump-simpl
他們兩個。猜猜看,核心文件僅在隨機名稱上有所不同。
當然,沒有-O2
輸出差異頗大。但這是預料之中的。
在第二個片段中,而不是'(_env - > env)'你是指'(\ env - > env)'? – ErikR
你的問題到底是什麼? – Zeta
第二個片段很奇怪。請將其重寫爲更有意義或添加評論。第一個片段只是'sth',因爲你不用'local'改變環境(只是返回已經設置的env)。 – ron