簡體   English   中英

延續單子-整數和字符串

[英]Continuation Monad - Int and String

《 Monads of the Monads》文章介紹了以下代碼:

ex3 = do
  a <- return 1
  b <- ContT (\fred -> "escape")
  return $ a+b

然后我可以執行它:

ghci> runContT ex3 show
"escape"

但是我不能跑步:

ghci> runContT ex3 id

<interactive>:51:14:
    Couldn't match type ‘[Char]’ with ‘Integer’
    Expected type: Integer -> [Char]
      Actual type: Integer -> Integer
    In the second argument of ‘runContT’, namely ‘id’
    In the expression: runContT ex3 id

如何return $ a+b類型檢查?

runCont ex3 show什么? runCont ex3 id怎么樣-好像不能接受Int + [Char] -但是為什么要編譯?

首先,讓我們看看Cont是如何定義的:

data Cont r a = Cont {runCont :: (a -> r) -> r}

如果放大此聲明,將會看到Cont包裝了一個函數,給定一個函數(a->r)會生成r 換句話說,它“隱藏” runCont內部類型為a (或r )的runCont 因此, do表達式中存在Cont (\\fred -> "escape")fred是一個函數,將被忽略)告訴我們rString ,並且整個表達式的runCont被固定為返回String類型的值,並且對於某些a只能接受a->String類型的函數,我們需要對其進行求解。

現在讓我們看看return是什么樣的:

instance Monad (Cont r) where
    return x = Cont ($ x)  -- given a function, pass x to it
    (Cont m) >>= f = -- f :: a -> Cont r b, which roughly means
                     -- f :: a -> (b->r) -> r
                     -- which would roughly be Cont (\g -> m (flip f g))
                     -- notice we pass f to m: f is the stuff that needs
                     -- executing when m needs to; f is continuation of m
                     let h g x = let (Cont n) = f x -- unwrap (b->r)->r
                                 in n g
                     in Cont (m . h)
    -- or Cont (\g -> m (($ g) . runCont . f)), if that's easier to read

注意>>=工作方式。 如果m不使用傳遞給它的函數-請記住, runCont可能會直接“隱藏”類型r的值,不一定是“ a ”類型的值-然后是“ continuation”( fred in Cont (\\fred -> "escape") )沒有被調用,您將觀察到“轉義”。

因此, a <- return 1表示a :: Integer ,顯然, b <- Cont (\\_ -> "escape")並不表示b :: String相反, b可以是任何類型-函數fred傳遞給Cont被忽略,因此任何返回String函數都可以使用-但是b的類型由表達式的其余部分固定。 return $ a + b只是表示Cont String Integer因為aInteger ,所以b也固定為Integer

此外,觀察到由定義showrunCont ex3 show注定作為最后一行的延續do表情:是指對線路return $ a+b ,所以你的意思傳遞類型的函數Integer -> r因為a+bInteger ,並且您打算傳遞a- a -> String類型的函數,因為r由表達式b <- Cont (\\_ -> "escape")

這樣,整個表達式等效於以下內容:

do
  a <- return 1
  b <- Cont (\_ -> "escape")
  return $ (a+b)
==
  return 1 >>= (\a -> (Cont (\_ -> "escape") >>= (\b -> return (a+b))))
== -- apply return rule
  Cont ($ 1) >>= (\a -> (Cont (\_ -> "escape") >>= 
                        (\b -> Cont ($ (a+b)))))
== -- apply >>= rule
  Cont (\g -> ($ 1) (($ g) . runCont . (\a -> (Cont (\_ -> "escape") >>= 
                                              (\b -> Cont ($ (a+b)))))))
== -- apply >>= rule
  Cont (\g -> ($ 1) (($ g) . runCont . (\a -> (Cont (\h -> 
        (\_ -> "escape") (($ h) . runCont . (\b -> Cont ($ (a+b)))))))))
== -- (\_ -> x) y == x
  Cont (\g -> ($ 1) (($ g) . runCont . (\a -> (Cont (\h -> "escape")))))
== -- marking unused variables with "_" for clarity
  Cont (\g -> ($ 1) (($ g) . runCont . (\_ -> (Cont (\_ -> "escape")))))
== -- ($ y) (\_ -> x) == x
  Cont (\g -> ($ g) $ runCont (Cont (\_ -> "escape")))
== -- runCont (Cont x) == x
  Cont (\g -> ($ g) (\_ -> "escape"))
== -- ($ y) (\_ -> x) == x
  Cont (\_ -> "escape")

暫無
暫無

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

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