I've been working on learning about the state monad. I'm working with trees, defined as follows... data Tree a = Unary (Tree a) | Binary (Tree a) (Tree a)| Ternary (Tree a) (Tree a) (Tree a) | Leaf a
What I'm currently trying to do is make a function with type signature randomize :: Tree a -> Tree Int that returns a tree where each leaf (Leaf a) is replaced by a leaf (Leaf 0) or a (Leaf 1) with equal probability.
I previously wrote a function I called label :: Enum b => Tree a -> b -> Tree b that traverses a Tree and replaces every Leaf a with a Leaf b where b is incremented every time a leaf is visited. It is defined as follows
label:: Enum b => Tree a -> b -> Tree b
label tree b = evalState (mapSucc (\s -> (s, succ s)) tree) b where
mapSucc f (Leaf a) = Leaf <$> state f
mapSucc f (Unary t1) = Unary <$> mapSucc f t1
mapSucc f (Binary t1 t2) = Binary <$> mapSucc f t1 <*> mapSucc f t2
mapSucc f (Ternary t1 t2 t3) = Ternary <$> mapSucc f t1 <*> mapSucc f t2 <*> mapSucc f t3
These seem to be very similar problems, you are weaving the state through each, you're just producing values differently. I tried...
randomize tree = evalState ( mapRandom (randomR (0,1)) tree) newStdGen where
mapRandom f (Leaf a) = Leaf <$> state f
mapRandom f (Unary t1) = Unary <$> mapRandom f t1
mapRandom f (Binary t1 t2) = Binary <$> mapRandom f t1 <*> mapRandom f t2
mapRandom f (Ternary t1 t2 t3) = Ternary <$> mapRandom f t1 <*> mapRandom f t2 <*> mapRandom f t3
however the compiler gave me the following
state.hs:55:41: error:
• No instance for (RandomGen (IO StdGen))
arising from a use of ‘randomR’
• In the first argument of ‘mapRandom’, namely ‘(randomR (0, 1))’
In the first argument of ‘evalState’, namely
‘(mapRandom (randomR (0, 1)) tree)’
In the expression:
evalState (mapRandom (randomR (0, 1)) tree) newStdGen
I thought Int was an instance of random, so I'm not really sure what to do to get an instance of Random, and if I did manage that if my thought process is on the right path. Would my solution work if I were to get an instance of random. I guess I'm not sure if my shortcoming stems from simply not knowing how to use System.Random or if I am not understanding the type of function I need. I've spent a significant amount of time trying to make randomize work but to no avail. Any help with understanding would be greatly appreciated.
Aucun commentaire:
Enregistrer un commentaire