2016-04-12 2 views
0

Я играю с привязками leveldb.Сбросьте слой из MonadResource

мне интересно, если это возможно, чтобы принять функцию как

MonadResource m => a -> m b 

и преобразовать его в

MonadResource m => m (a -> IO b)) 
+0

В общем, это невозможно, потому что 'a' идет от отрицательного к положительному положению (я думаю). Вы можете получить лучшую помощь, если немного поработаете над своей проблемой. Какую функцию LevelDB вы смотрите на этот тип? Это библиотека leveldb-haskell? – hao

+0

Почему вы хотите это сделать? Если вы выполняете какое-либо действие IO внутри него, используйте 'liftIO'. – Sibi

+0

Это библиотека leveldb-haskell. – sfultong

ответ

3

Это, безусловно, может быть сделано, но это опасно. Продемонстрируем сначала хау, путем извлечения внутреннего состояния ResourceT:

import Control.Monad.IO.Class 
import Control.Monad.Trans.Resource 
import Control.Monad.Trans.Resource.Internal 

data Foo = Foo Int 
    deriving Show 

getFoo :: MonadResource m => Int -> m Foo 
getFoo i = fmap snd $ allocate 
    (do 
     putStrLn $ "allocating Foo with " ++ show i 
     return $ Foo i) 
    (\(Foo x) -> putStrLn $ "Freeing Foo " ++ show x) 

stripLayer :: MonadResource m => (a -> ResourceT IO b) -> m (a -> IO b) 
stripLayer f = do 
    is <- liftResourceT getInternalState 
    return $ \a -> runInternalState (f a) is 

main :: IO() 
main = do 
    getFoo' <- runResourceT $ stripLayer $ getFoo 
    getFoo' 42 >>= print 

К сожалению, выход из этого является не то, что мы будем надеяться на:

allocating Foo with 42 
Foo 42 

Обратите внимание, как «Освобождение» линия никогда не называется. Это связано с тем, что к моменту использования getFoo' вызов runResourceT уже завершен, и мы гарантируем, что все ресурсы будут освобождены. Вы, можете безопасно уйти с этим трюком, если вы дисциплинированы и убедитесь, что все живет внутри вызова runResourceT, но система типов вам не поможет. Чтобы увидеть, как это будет выглядеть:

main :: IO() 
main = runResourceT $ do 
    getFoo' <- stripLayer $ getFoo 
    liftIO $ getFoo' 42 >>= print 
Смежные вопросы