[英]Can some one explain how to use lift in haskell?
我試着通過例子來理解起重原理,發現了這個:
然后,如果我將它的lift (lift (putStrLn "bla-bla"))
更改為putStrLn "bla-bla"
,編譯器會拋出錯誤!
我這樣做是基於我的理解: do
塊只是語法糖,每一行的結果都傳遞到下一行。 如果下一行不使用從上一行傳遞的 args,我認為 args 的類型不會導致類型沖突。
以波紋管為例,而x<- getLine
可以通過編譯
test:: IO ()
test = do
x <- getLine -- discarded and compiler don't care it type
let a = "bla-bla" -- discarded and compiler don't care it type
putStrLn $ "You type are discarded: "
現在回到calculations
函數:
type Data = Map.Map Int String
type StateIO = StateT Data IO
type MaybeStateIO a = MaybeT StateIO a
calculations :: MaybeStateIO ()
calculations = do
lift (lift (putStrLn "bla-bla")) -- if I change this to `putStrLn "bla-bla"`, it failed compiling.
lift (modify (Map.insert 3 "3"))
lift (modify (Map.insert 1 "1"))
mb <- lift (get >>= (return . Map.lookup 1))
lift (lift (print mb))
main = runStateT (runMaybeT calculations) Map.empty
我不明白編譯器需要提升putStrLn "bla-bla"
。
do
塊最后一行的返回值與函數的返回值匹配還不夠嗎?
在這個例子中,編譯器如何根據函數的簽名來決定do block
的值類型?
誰能幫我解釋一下電梯? 它是如何工作的,何時使用等。
calculations
的值是一個MaybeStateIO
值。 這就是你正在操作的 monad,所以這就是do
塊的每一行都必須產生的內容。 但是putStrLn "bla-bla"
不會產生MaybeStateIO
值; 它只是產生一個IO
值。 第一個lift
取那個IO
值並返回一個StateIO
值; 第二次lift
采用StateIO
值並返回MaybeStateIO
值。
記住,
do
a
b
只是a >> b
語法糖,並且(>>) :: Monad m => ma -> mb -> mb
需要來自同一個 monad 的值作為參數。 只有單子的“返回值”( a
和b
)會因行而異; monad m
本身是固定的。
do
塊最后一行的返回值與函數的返回值匹配還不夠嗎?
不,因為這意味着您可以編寫一個do
塊,例如,第一項將使用Monad
的[]
實例,而下一項將使用例如Maybe
或IO
,但是x <- some_list
對putStrLn x
的列表? do
塊中的所有行都應該是ma
類型,其中m
是Monad
的相同實例,並且每行a
s 可以有不同的類型。 如果你寫一個 do 塊:
foo = do x <- exp1 exp2
然后將其轉換為exp 1 >>= \x -> exp 2
,並且由於(>>=) :: Monad m => ma -> (a -> mb) -> mb
在兩個操作數共享相同的情況下運行monad m
,因此這意味着exp 1 :: ma
和exp 2 :: mb
因此需要使用相同的單子類型m
。
您需要執行兩次提升,因為該行應該具有類型MaybeT (StateT Data IO) a
而putStrLn "bla-bla"
具有IO a
,因此需要一次lift :: (MonadTrans t, Monad m) => ma -> tma
將其提升到StateT Data IO a
和另一個最終將其提升到MaybeT (StateT Data IO) a
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.