我的解決方案利用了Haskell術語的邏輯結構。大家都知道,具有返回類型t的Haskell中的函數可以轉化爲具有返回類型(Monad m)=> m t的monadic函數。因此,如果「綁定」功能可以使其程序文本「monadified」適當,結果將是一個monad變換器。
的癥結是沒有理由的「綁定」操作的「monadification」應滿足法律,特別是關聯性。這是截斷消除的地方。截斷消除定理對內聯所有允許綁定,案例分析和應用程序的程序文本產生影響。而且,特定術語的所有計算最終都在一個地方執行。
由於「綁定」的類型參數是剛性的,「綁定」的右手側的用途可以通過返回值索引。這些術語最終位於返回結構中使「綁定」關聯的位置,因此右側的使用必須在「monadified」「綁定」中關聯,並且生成的結構是monad。
這實在是毛茸茸的,所以這裏是一個例子。請看下面的列表嚴格單子:
rseq x y = case x of x:xs -> (x:xs) : y [] -> [] : y
evalList (x:xs) = rseq x (evalList xs) evalList [] = []
instance Monad [] where return x = [x] ls >>= f = concat (evalList (map f ls))
評價此順序導致標準ListT(不是一個真正的單子)。然而,通過切割消除:
instance Monad [] where return x = [x] ls >>= f = case ls of [] -> [] x:xs -> case f x of y:ys -> (y:ys) ++ (xs >>= f) [] -> [] ++ (xs >>= f)
這提供了準確的評估,以進行 「monadified。」
響應於彼得Pudlak:
如果有問題的單子的類型是一些功能類型(方便的是教會編碼的所有數據類型),則該函數類型是由裝飾轉換所有返回的類型與轉換後的monad值。這是monadification的類型部分。 monadification的價值部分使用「return」提升純粹的功能,並使用「綁定」將它們與monad類型的居民的使用結合起來,從而保留了原始程序文本的評估順序。
嚴格列表單子被給出作爲評價順序不相關聯地構成,由該ListT使用相同的評價順序的嚴格列表單子的事實作爲見證的一個例子。
爲了完成這個例子,列表單子教會編碼是:
data List a = List (forall b. b -> (a -> List a -> b) -> b)
Monadified,就變成:
data ListT m a = ListT (forall b. m b -> (a -> List a -> m b) -> m b)
cons x xs = \_ f -> f x xs
nil = \x _ -> x
instance (Monad m) => Monad (ListT m) where return x = cons x nil ls >>= f = ls nil (\x xs -> f x >>= \g -> g (liftM (nil ++) (xs >>= f)) (\y ys -> liftM (cons y ys ++) (xs >>= f))
爲了詳細說明上述情況,切步消力數值全部使用堆棧紀律,確保在結構結果的順序評估順序一致消耗 - 這是以潛在的價格多次運行相同的動作。 [技術上,你需要的是切除近似值:A是B的切除消除(近似值),如果對於B的每個有限近似值,存在A的有限近似值,使得A是切消除B.]
我希望有所幫助。
'ST'是另一個明顯的例子,但它也違反了你的「純粹」單子限制。 –
所以你正在尋找一種類型T,使得有一個滿足單子定律的實例Monad(T Identity),但是這樣T不能滿足monad變換器的定律? – bennofs
@GaneshSittampalam好點,我在「排除列表」中添加了「ST」。 –