So far I wrote the following code, I tested all the functions, and they work well, but testing the indexNodesM function, it just does not work, I think the put method is not working right.
The given test cases are:
execState (indexNodesM exTree1) 0 == 6
evalState (indexNodesM exTree1) 0 == Node (5,3) (Node (3,1) Leaf (Node (2,11) (Node (0,7) Leaf Leaf) (Node (1,5) Leaf Leaf))) (Node (4,13) Leaf Leaf)
For example, executing execState (indexNodesM exTree1) 0
gives 0 as result.
My code:
{-# LANGUAGE InstanceSigs #-}
import Control.Monad (ap)
newtype State s a = S { runState :: s -> (a,s) }
evalState :: State s a -> s -> a
evalState (S f) s = fst (f s)
execState :: State s a -> s -> s
execState (S f) s = snd (f s)
instance Functor (State s) where
fmap :: (a -> b) -> (State s a) -> (State s b)
fmap f (S g) = S (\n -> (f (fst (g (n))), n))
instance Applicative (State s) where
pure = return
(<*>) = ap
instance Monad (State s) where
return :: a -> (State s a)
return a = S (\n -> (a, n))
(>>=) :: (State s a) -> (a -> State s b) -> (State s b)
(>>=) (S f) g = S (\n -> runState (g (fst (f n))) (n))
get :: State s s
get = S (\n -> (n, n))
put :: s -> State s ()
put x = S (\n -> ((),x))
modify :: (a -> a) -> State a ()
modify f = S (\n -> ((), f n))
data Tree a = Leaf | Node a (Tree a) (Tree a)
deriving (Eq, Ord, Show)
exTree1 :: Tree Int
exTree1 =
Node 3
(Node 1
Leaf
(Node 11
(Node 7
Leaf
Leaf)
(Node 5
Leaf
Leaf)))
(Node 13
Leaf
Leaf)
indexNodesM :: Tree a -> State Int (Tree (Int, a))
indexNodesM Leaf = return Leaf
indexNodesM (Node x tree1 tree2) = do
i <- get
put (i + 1)
t1 <- indexNodesM tree1
t2 <- indexNodesM tree2
return (Node (i, x) t1 t2)
What could be the problem? Thanks in advance.
Welcome to Stack Overflow. If you fix the definition of your State monad, then it will work as you expect. The problem with your current implementation is that neither >>=
nor fmap
actually update the state, as you always use fst
to throw the state away and then use the old state. Here is the corrected implementation:
import Control.Monad (ap, liftM)
...
instance Functor (State s) where
fmap = liftM
instance Applicative (State s) where
pure = return
(<*>) = ap
instance Monad (State s) where
return :: a -> (State s a)
return a = S (\n -> (a, n))
(>>=) :: (State s a) -> (a -> State s b) -> (State s b)
(>>=) (S f) g = S (\n -> let (a, n') = f n in runState (g a) n')
Now your test cases work almost as expected, except that indexNodesM
labels the nodes from left to right:
*Main> execState (indexNodesM exTree1) 0 == 6
True
*Main> evalState (indexNodesM exTree1) 0
Node (0,3) (Node (1,1) Leaf (Node (2,11) (Node (3,7) Leaf Leaf) (Node (4,5) Leaf Leaf))) (Node (5,13) Leaf Leaf)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.