2016-05-16 63 views
-2

我認爲如果兩個下面的表達式是等價的:功能當地哈斯克爾讀者單子

env <- ask 
local (\_ -> env) sth 

和:

local (\env -> env) sth 

如果不是,它被帶到參數的lambda?

+2

在第二個片段中,而不是'(_env - > env)'你是指'(\ env - > env)'? – ErikR

+2

你的問題到底是什麼? – Zeta

+0

第二個片段很奇怪。請將其重寫爲更有意義或添加評論。第一個片段只是'sth',因爲你不用'local'改變環境(只是返回已經設置的env)。 – ron

回答

2

不確定你的問題是關於什麼的,但讓我們試試。

所以你問如果

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輸出差異頗大。但這是預料之中的。