Created
October 10, 2012 09:37
-
-
Save uduki/3864382 to your computer and use it in GitHub Desktop.
How to use Free Monad
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE DeriveFunctor, FlexibleInstances, FlexibleContexts #-} | |
import Control.Monad.Trans | |
import Control.Monad.Trans.Maybe | |
import Control.Monad.State | |
import qualified Control.Monad.Free as F | |
import qualified Data.Foldable as DF | |
import Prelude hiding (head,last) | |
{- | |
- ベースにするデータ構造をFunctorで定義する。 | |
- Monadインターフェースを与えるのがFreeモナド。 | |
- 実装したい機能はFreeモナドに乗せた状態で作成する。 | |
-} | |
data ListF a = Nil | Node a (ListF a) | |
deriving (Functor, Show) | |
instance DF.Foldable ListF where | |
foldr f v Nil = v | |
foldr f v (Node x xs) = x `f` DF.foldr f v xs | |
type List a = F.Free ListF a | |
empty :: List a | |
empty = F.liftF Nil | |
singleton :: a -> List a | |
singleton a = F.liftF $ Node a Nil | |
cons :: a -> List a -> List a | |
cons a (F.Free xs) = F.Free (Node (F.Pure a) xs) | |
cons a (F.Pure x) = cons a (singleton x) | |
head :: List a -> a | |
head = F.iter (\(Node x _) -> x) | |
last :: List a -> a | |
last = F.iter f | |
where | |
f (Node x Nil) = x | |
f (Node _ xs) = f xs | |
fromList :: [a] -> List a | |
fromList = foldr cons empty | |
sum1 :: Num a => List a -> a | |
sum1 = F.iter f | |
where | |
f Nil = 0 | |
f (Node x xs) = x + f xs | |
sum2 :: Num a => List a -> a | |
sum2 = DF.foldl' (+) 0 | |
sum3 :: Num a => List a -> a | |
sum3 = DF.foldl1 (+) | |
sum4 :: (Num a, Show a) => List a -> a | |
sum4 xs = head $ flip execStateT 0 $ do | |
DF.forM_ xs $ \x -> do | |
n <- get | |
put (x + n) | |
filterEven :: (Integral a, Eq a) => List a -> List (Maybe a) | |
filterEven xs = runMaybeT $ do | |
x <- lift xs | |
if x `mod` 2 == 0 | |
then return x | |
else fail "" | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment