如果我這樣定義「綁定」功能:單子「綁定」功能的問題
(>>=) :: M a -> (a -> M' b) -> M' b
將這個定義幫助我,如果我想要的結果是一個新的單子類型,或者我應該使用相同的Monad但與之前的b在相同的Monad框中?
如果我這樣定義「綁定」功能:單子「綁定」功能的問題
(>>=) :: M a -> (a -> M' b) -> M' b
將這個定義幫助我,如果我想要的結果是一個新的單子類型,或者我應該使用相同的Monad但與之前的b在相同的Monad框中?
正如我在評論中提到的,我不認爲這樣的操作可以安全地定義爲一般單子(例如M = IO
,M' = Maybe
)。
然而,如果M是安全地轉換爲M」,則此綁定可被定義爲:
convert :: M1 a -> M2 a
...
(>>=*) :: M1 a -> (a -> M2 b) -> M2 b
x >>=* f = convert x >>= f
反之,
convert x = x >>=* return
一些這樣的安全轉換方法是maybeToList
(也許→ []),listToMaybe
([] →也許),stToIO
(ST RealWorld → IO),...請注意,對於任何monads,沒有通用的convert
方法。
除身份。 – luqui 2010-07-16 22:40:59
這個定義不僅沒有幫助,而且會嚴重混淆未來的代碼讀者,因爲它會打破所有使用它的期望。
例如,M和M'是否應該是Monads?如果是這樣,那麼他們是如何定義的?請記住:>>=
的定義是Monad定義的一部分,並且在任何地方用於定義其他Monad使用函數 - 除return
和fail
本身之外的每個函數。
另外,您是否選擇使用哪個M和M,還是計算機?如果是這樣,那麼你如何選擇?它是否適用於任何兩個Monad實例,或者是否存在您想要的Monad子集 - 或者M的選擇決定了M'的選擇?
這有可能使像你寫的功能,但它肯定是一個很多比>>=
更加複雜,而且會產生誤導,殘酷的,可能是災難性的,試圖填滿你的函數爲>>=
「穿衣服。
你可能想看看這個樣本從奧列格:http://okmij.org/ftp/Computation/monads.html#param-monad
這可能是做一個複雜的事情,但它在某些情況下是可行的。基本上,如果他們是可以在裏面看到的monads(例如Maybe
或您寫的monad),那麼您可以定義這樣的操作。
有時候很方便(在GHC中)有一件事是用你自己的一個替換Monad
類。如果你定義了return, >>=, fail
,你仍然可以使用do
表示法。這裏有可能會像你想要的一個例子:
class Compose s t where
type Comp s t
class Monad m where
return :: a -> m s a
fail :: String -> m a
(>>=) :: (Compose s t) => m s a -> (a -> m t b) -> m (Comp s t) b
(>>) :: (Compose s t) => m s a -> m t b -> m (Comp s t) b
m >> m' = m >>= \_ -> m'
然後,您可以控制哪些類型可以使用基於您定義的Compose
哪些實例在綁定運營商進行測序。當然,你經常需要Comp s s = s
,但你也可以用它來定義各種瘋狂的東西。例如,你可能在你的monad中有一些操作,絕對不能跟隨任何其他操作。想要執行這個靜態?定義一個空數據類型data Terminal
並且不提供Compose Terminal t
的實例。
此方法不適用於從(比如說)Maybe
轉換爲IO
,但它可用於攜帶有關您所做的某些類型級別的數據。
如果你確實想改變單子,你可以修改類定義上述弄成
class Compose m n where
type Comp m n
(>>=*) :: m a -> (a -> n b) -> (Compose m n) b
class Monad m where
return :: a -> m a
fail :: String -> m a
(>>=) :: Compose m n => m a -> (a -> n b) -> (Compose m n) b
m >>= f = m >>=* f
(>>) :: Compose m n => m a -> (n b) -> (Compose m n) b
m >> n = m >>=* \_ -> n
我用前者風格善始善終,但我想,後者的想法也可能在某些情況下有用。
如果是這樣,那麼'M'和'M''不是(只)單子。 – kennytm 2010-07-16 18:36:44
...以及爲什麼要將一個monad轉換爲另一個monad?例如,我認爲將IO轉換爲Maybe可能不安全。雖然可以組成monad('IO(也許a)')。 – kennytm 2010-07-16 18:48:41
轉換爲不同的Monad,以便直觀地進行更多不同的計算。但也許這沒有用,對吧?我正在尋找例子來證明有這樣的理由。 – Rn2dy 2010-07-16 18:53:33