Haskell 用我的状态 monad 标记二叉树的节点不起作用
Haskell labeling the nodes of a binary tree with my state monad does not work
到目前为止我写了下面的代码,我测试了所有的功能,它们都运行良好,但是测试indexNodesM功能,它不起作用,我认为put方法不正确。
给定的测试用例是:
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)
例如,执行 execState (indexNodesM exTree1) 0
结果为 0。
我的代码:
{-# 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)
可能是什么问题?提前致谢。
欢迎来到 Stack Overflow。如果你修正了你的 State monad 的定义,那么它就会像你期望的那样工作。当前实现的问题是 >>=
和 fmap
都没有实际更新状态,因为您总是使用 fst
丢弃状态然后使用旧状态。这是更正后的实现:
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')
现在您的测试用例几乎按预期工作,除了 indexNodesM
从左到右标记节点:
*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)
到目前为止我写了下面的代码,我测试了所有的功能,它们都运行良好,但是测试indexNodesM功能,它不起作用,我认为put方法不正确。
给定的测试用例是:
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)
例如,执行 execState (indexNodesM exTree1) 0
结果为 0。
我的代码:
{-# 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)
可能是什么问题?提前致谢。
欢迎来到 Stack Overflow。如果你修正了你的 State monad 的定义,那么它就会像你期望的那样工作。当前实现的问题是 >>=
和 fmap
都没有实际更新状态,因为您总是使用 fst
丢弃状态然后使用旧状态。这是更正后的实现:
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')
现在您的测试用例几乎按预期工作,除了 indexNodesM
从左到右标记节点:
*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)