131018.2 · 6a302f15b2ac2fa54f1db6e9788eb1e91a4e7501
update
reading declarations
Changes to Monads/. All files
@@ -13,8 +13,12 @@ import Text.Printf (printf) -- | @Node@ corresponds to any value representable as a Dot node. class Node a where+ -- | A uniquely identifying string for this node. name :: a -> String- label :: a -> Maybe String -- labels may not contain double quotes++ -- | Labels cannot contain double quotes. If no label is specified,+ -- then `name` will be used instead.+ label :: a -> Maybe String -- | Every edge is a directed edge from one node to another. data Edge a = Edge { from :: a, to :: a, elabel :: Maybe String }@@ -26,9 +30,21 @@ instance Node SimpleNode where name = sname label = slabel +-- | Create a new @SimpleNode@ with a name.+simpleNode :: String -- ^ The name of the node.+ -> SimpleNode+simpleNode name = SimpleNode name Nothing +-- | Same as `simpleNode`, but allows a label independent of the name.+simpleNodeLabel :: String -- ^ The name of the node.+ -> String -- ^ The label of the node.+ -> SimpleNode+simpleNodeLabel name label = SimpleNode name (Just label)++-- | @Graph@ corresponds to a graph expressible in the Dot language. data Graph a = Graph { nodes :: [a], edges :: [Edge a] } +-- | Converts a graph to its Dot representation. dot :: Node a => Graph a -> String dot (Graph ns es) = printf "digraph G {\n\t%s\n\t%s\n}" nodes edges where nodes = intercalate "\n\t" $ map dnode ns@@ -44,6 +60,7 @@ instance Monoid (Graph a) where mempty = Graph [] [] (Graph ns1 es1) `mappend` (Graph ns2 es2) = Graph (ns1 ++ ns2) (es1 ++ es2) +-- | A monad that constructs values representable in the Dot language. newtype Dotter n a = Dotter { runDotter :: (a, Graph n) } instance Monad (Dotter n) where@@ -51,30 +68,25 @@ instance Monad (Dotter n) where Dotter (a, g) >>= f = Dotter (a', g `mappend` g') where (a', g') = runDotter (f a) -simpleNode :: String -> SimpleNode-simpleNode name = SimpleNode name Nothing--simpleNodeLabel :: String -> String -> SimpleNode-simpleNodeLabel name label = SimpleNode name (Just label)-+-- | Adds a node to the current graph. addNode :: Node a => a -> Dotter a () addNode node = Dotter ((), Graph [node] []) -addEdge :: Node a => a -> a -> Dotter a ()+-- | Adds a directed edge to the current graph.+addEdge :: Node a+ => a -- ^ The "from" node.+ -> a -- ^ The "to" node.+ -> Dotter a () addEdge n1 n2 = Dotter ((), Graph [] [Edge n1 n2 Nothing]) -addEdgeLabel :: Node a => a -> a -> String -> Dotter a ()+-- | Same as `addEdge`, but with an edge label.+addEdgeLabel :: Node a+ => a -- ^ The "from" node.+ -> a -- ^ The "to" node.+ -> String -- ^ The edge label.+ -> Dotter a () addEdgeLabel n1 n2 label = Dotter ((), Graph [] [Edge n1 n2 (Just label)]) +-- | Evaluate an instance of the `Dotter` monad to its Dot representation. eval :: Node a => Dotter a () -> String eval = dot . snd . runDotter--testGraph :: Dotter SimpleNode ()-testGraph = do- let (n1, n2) = (simpleNode "A", simpleNode "B")- addNode n1- addNode n2- addEdge n1 n2--main :: IO ()-main = putStrLn $ eval testGraph
@@ -6,6 +6,7 @@ where import qualified System.Random as R +-- | A random monad that works with any generator satisfying `RandomGen`. newtype MRand g a = MRand (g -> (a, g)) instance R.RandomGen g => Monad (MRand g) where@@ -14,21 +15,31 @@ instance R.RandomGen g => Monad (MRand g) where MRand m1 = f a in m1 g') +-- | Evaluate an instance of the `MRand` monad with a source of randomness. eval :: R.RandomGen g => MRand g a -> g -> a eval (MRand f) g = fst (f g) +-- | Provides a random value. random :: (R.RandomGen g, R.Random a) => MRand g a random = MRand R.random -randomR :: (R.RandomGen g, R.Random a) => (a, a) -> MRand g a+-- | Provides a random value in a range.+randomR :: (R.RandomGen g, R.Random a)+ => (a, a) -- ^ An inclusive range [lo, hi].+ -> MRand g a randomR r = MRand (R.randomR r) +-- | Provides an infinite list of random values. randoms :: (R.RandomGen g, R.Random a) => MRand g [a] randoms = MRand (\g -> let (g', g'') = R.split g in (R.randoms g', g'')) -randomRs :: (R.RandomGen g, R.Random a) => (a, a) -> MRand g [a]+-- | Provides an infinite list of random values in a range.+randomRs :: (R.RandomGen g, R.Random a)+ => (a, a) -- ^ An inclusive range [lo, hi].+ -> MRand g [a] randomRs r = MRand (\g -> let (g', g'') = R.split g in (R.randomRs r g', g'')) +-- Demonstrates two infinite, independent sources of integers. two :: R.RandomGen g => MRand g ([Int], [Int]) two = do xs <- randomRs (1, 10)@@ -40,4 +51,3 @@ main = do let (xs, ys) = eval two g print $ take 10 xs print $ take 10 ys-