我已经得到了大量的IConnection conn => conn -> IO()函数,我需要执行以正确设置数据库。现在,它不是很漂亮,但我对Haskell的初学者太多,无法使它更好。
setup :: IConnection conn => conn -> IO ()
setup conn = do
setupUtterances conn
commit conn
setupSegments conn
commit conn
setupLevels conn
commit conn
setupLevelLevel conn
commit conn
setupTCLevelLevel conn
commit conn
setupPaths conn
commit conn
setupLabelTypes conn
commit conn
setupLegalLabels conn
commit conn
setupTracks conn
commit conn
setupVariables conn
commit conn
setupFeatures conn
commit conn
setupAssociations conn
commit conn
return ()
怎么缩短呢?我在玩
sequence $ map ($ conn) [func1, func2,...]
但是我不能让它工作。建议吗?
setup conn = mapM_ ($ conn) $ intersperse commit
[ setupUtterances,
, setupSegments
, setupLevels
, setupLevelLevel
, setupTCLevelLevel
, setupPaths
, setupLabelTypes
, setupLegalLabels
, setupTracks
, setupVariables
, setupFeatures
, setupAssociations
, _ -> return ()]
intersperse
将commit
置于所有动作之间,mapM_ ($conn)
将conn
馈送至所有IO
动作。最后的_ -> return ()
是为了确保在最后调用commit
。
简单地收集函数列表,映射函数应用程序并分散提交。然后,您只需按顺序执行您的操作并手动调用最终提交:
import Data.List (intersperse)
-- ... other things
setup :: IConnection => -> IO ()
setup conn =
let ops = [ setupUtterances
, setupSegments
, setupLevels
, setupLevelLevel
, setupTCLevelLevel
, setupPaths
, setupLabelTypes
, setupLegalLabels
, setupTracks
, setupVariables
, setupFeatures
, setupAssociations
]
acts = map ($ conn) $ intersperse commit ops
in sequence_ acts >> commit conn
我今天想打代码高尔夫。一行代码(好吧,它开始是这样的):
import Control.Monad.Trans.Reader
-- | Run a sequence of actions with the same connection, committing that
-- connection after each action.
runSetup :: IConnection conn => [conn -> IO ()] -> conn -> IO ()
runSetup = runReaderT . mapM_ withCommit
where withCommit action = ReaderT action >> ReaderT commit
setup = runSetup actions
where actions = [ setupUtterances
, setupSegments
, setupLevels
, setupLevelLevel
, setupTCLevelLevel
, setupPaths
, setupLabelTypes
, setupLegalLabels
, setupTracks
, setupVariables
, setupFeatures
, setupAssociations
]
这里的核心思想是Connection -> IO ()
与ReaderT Connection IO ()
相同:IO ()
"缺少"Connection
。ReaderT
允许您将commit
、setupUtterances
、setupSegments
和好友不是作为函数,而是作为共享一个共同的隐式Connection
的动作。ReaderT Connection IO
只是一个单子,所以你可以很容易地在每个动作之后添加一个commit
。