2012-02-09 39 views
6

我目前正在撰寫一個項目,我大量使用ListT monad變壓器。使用普通列表時,實現非確定性非常容易。然而,一旦我不得不將我的代碼轉換爲ListT,它就變得更加複雜了。如何幹淨地轉換列表和ListT monad變換器?

舉個簡單的例子:從[a]ListT a實際需要合成的兩種功能轉換:

conv :: (Monad m) => [a] -> ListT m a 
conv = ListT . return 

雖然很簡單,我很驚訝這不是已經存在。

問題:

  • 有一些更好的方式來處理這種情況需要一個單子轉換確定性?
  • 是否有任何技術/庫在清單和ListT之間來回轉換?

確切的原因是相當複雜的,所以我真的不想闡述太多。

回答

6

我不認爲有這樣的圖書館;畢竟,conv是一個令人難以置信的簡單功能,而其他方式只是runListT

conv類似於liftMaybe使用MaybeT時,常常希望:

liftMaybe :: (Monad m) => Maybe a -> MaybeT m a 
liftMaybe = MaybeT . return 

我會建議將其命名爲沿liftList線的東西。

至於對非確定性更好的單子轉換得好,我建議採取看看logict包的基礎上,奧列格的LogicT變壓器,這是基於連續的回溯邏輯單子與some helpful operations。作爲獎勵,由於[]MonadLogic的實例,所以這些操作也可以在列表上進行。


有趣的是,我們可以定義可以推廣的convliftMaybe模式功能:

import Data.Foldable (Foldable) 
import qualified Data.Foldable as F 

choose :: (Foldable t, MonadPlus m) => t a -> m a 
choose = F.foldr (\a b -> return a `mplus` b) mzero 

這將可能使你的代碼相當混亂,所以我不建議使用它:)

+0

是的,我同意'conv'是一個簡單的函數。我只是感到驚訝,它不在那裏。 「ListT」模塊中幾乎沒有任何實用程序,這讓我覺得我重新發明了方向盤。就這樣。 – julkiewicz 2012-02-09 16:41:37

0

幾個月後,我剛剛遇到了這個問題,因爲我想知道類似這樣的事情。所以,我想出了以下內容:

{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-} 

import Control.Monad.Trans.Class 
import Control.Monad.Trans.Maybe 
import Control.Monad.Trans.List 


-- | Minimal implementation: either joinLift or joinT 
class (MonadTrans t, Monad m) => MonadTransJoin t m | m -> t, t -> m where 
    joinLift :: (Monad m', Monad (t m')) => m' (m a) -> t m' a 
    joinLift = joinT . lift 

    joinT :: (Monad m', Monad (t m')) => t m' (m a) -> t m' a 
    joinT = (>>= (joinLift . return)) 


instance MonadTransJoin MaybeT Maybe where 
    joinLift = MaybeT 
    joinT = (>>= maybe mzero return) 

instance MonadTransJoin ListT [] where 
    joinLift = ListT 
    joinT = (>>= foldr mcons mzero) 
     where mcons x xs = return x `mplus` xs 

到目前爲止好,我爲ListT/[]joinT方法看起來像它有事情做與ehird的choose

但是,這樣做的問題是monad變換器和monad的行爲之間並沒有統一的接口,monad的行爲賦予它的基本monad。我們有MaybeT :: m (Maybe a) -> MaybeT m aListT :: m [a] -> ListT m a,但是OTOH我們有StateT :: (s -> m (a, s)) -> StateT s m a。我不知道是否有辦法解決這個問題 - 它肯定需要

相關問題