顯然Concurrent a
相同Cont Action a
其中Cont
是延續單子。下面是延續一個簡單的解釋:
- 考慮函數
f :: a -> b
一些任意類型的a
和b
。我們想把這個函數轉換成連續傳遞樣式。我們如何做?
- 假設我們有一個延續
k :: b -> r
,它將返回值f
作爲輸入,並且它自己返回任意類型的值r
。在此之後,我們可以將f
轉換爲CPS。
- 讓
g :: a -> (b -> r) -> r
成爲f
的CPS版本函數。請注意,它需要一個附加參數(即繼續k
)並返回應用於其輸出b
的k
的結果。
讓我們舉一個實際的例子,其中f
是謂語功能odd :: Int -> Bool
:
odd :: Int -> Bool
odd n = n `mod` 2 == 1
這裏是寫在延續傳遞風格相同的功能:
odd' :: Int -> (Bool -> r) -> r
odd' n k = k (n `mod` 2 == 1)
的(Bool -> r) -> r
部分可以抽象出作爲延續單子:
data Cont r a = Cont { runCont :: (a -> r) -> r }
odd' :: Int -> Cont r Bool
odd' n = return (n `mod` 2 == 1)
instance Monad (Cont r) where
return a = Cont (\k -> k a)
m >>= f = Cont (\k -> runCont m (\a -> runCont (f a) k))
請注意,對於某些任意類型r
,延續k
的類型爲Bool -> r
。因此,延續k
可以是以Bool
作爲參數的任何函數。例如:
cont :: Bool -> IO()
cont = print
main :: IO()
main = odd' 21 cont
然而,在Concurrent
的情況下,這是r
不是任意的。它專門用於Action
。事實上,我們可以定義Concurrent
作爲一種代名詞Cont Action
如下:
type Concurrent = Cont Action
現在,我們並不需要實現Monad
實例Concurrent
,因爲它是與上述定義相同Monad
實例Cont r
。
runConcurrent :: Concurrent a -> ContinuationPseudoMonad a
runConcurrent (Concurrent g) = g
instance Monad Concurrent where
return a = Concurrent (\k -> k a)
m >>= f = Concurrent (\k -> runConcurrent m (\a -> runConcurrent (f a) k))
注意無處在instance Monad Concurrent
定義有我們利用了Action
。這是因爲Concurrent = Cont Action
和Cont r
的monad實例透明地使用r
。
你的問題是如何定義'Concurrent'的'return'和'>> =',就像你上面定義的那樣? – rampion
此外,輕微的錯字 - 我認爲你的意思是'數據Concurrent a = Concurrent(ContinuationPseudoMonad a)',因爲'數據Concurrent a = Concurrent ContinuationPseudoMonad a'是一個錯誤。 – rampion
我已根據您的說法進行了相應更正。事情是我沒有成功掌握什麼是「繼續 - >行動」。這個抽象的名字會很棒。 –