Skip to content

Instantly share code, notes, and snippets.

@alucky0707
Created October 8, 2013 14:47
Show Gist options
  • Save alucky0707/6885920 to your computer and use it in GitHub Desktop.
Save alucky0707/6885920 to your computer and use it in GitHub Desktop.
HaskellでGo言語のdefer文してみる with Freeモナド ref: http://qiita.com/alucky0707/items/156b2b013e16f27cb8d0
{-# LANGUAGE DeriveFunctor, LambdaCase #-}
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.Free
import System.IO
type Defer m = FreeT (DeferF m) m
data DeferF m cont
= Defer (Defer m ()) cont
| Scope (Defer m ()) cont deriving (Functor)
defer :: Monad m => Defer m a -> Defer m ()
defer d = liftF $ Defer (d >> return ()) ()
scope :: Monad m => Defer m a -> Defer m ()
scope d = liftF $ Scope (d >> return ()) ()
runDefer :: Monad m => Defer m a -> m a
runDefer = runDefer' []
where
runDefer' :: Monad m => [Defer m ()] -> Defer m a -> m a
runDefer' xs = runFreeT >=> \case
Free (Defer x next) -> runDefer' (x:xs) next
Free (Scope x next) -> runDefer' [] x >> runDefer' xs next
Pure x -> (unless (null xs) $ runDefer' [] $ mapM_ id xs) >> return x
-- ここからは試し
test :: Defer IO ()
test = do
h <- liftIO $ openFile "hello.txt" ReadMode
defer $ hClose h
liftIO $ hGetLine h >>= putStrLn
main = runDefer test
file, err := os.Open(filename)
if err != nil {
return err
}
//ここは関数を抜けるときに呼ばれる
defer file.Close()
hello :: Defer IO ()
hello = do
h <- liftIO $ openFile "hello.txt" ReadMode
defer $ hClose h
liftIO $ hGetLine h >>= putStrLn
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment