【发布时间】:2016-10-23 10:00:17
【问题描述】:
对于编程练习,我应该采用数据类型的树
data Tree a = Branch (Tree a) a (Tree a) | Leaf
deriving (Eq, Ord, Show)
并用一个Int标记每个a,越来越多地,深度优先,使用状态单子,并计算单子动作的数量。例如,表达式
let tree = Branch (Branch Leaf "B" Leaf) "A" Leaf
in run (label tree) 42
应该评估为
(Branch (Branch Leaf (42, "B") Leaf) (43, "A") Leaf
, Counts {binds = 10,returns = 5, gets = 4, puts = 2})
状态的类型是:
newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }
这是我对label 和run 的实现
label :: MonadState m Int => Tree a -> m (Tree (Int, a))
label Leaf = return Leaf
label (Branch left value right) = do
newLeft <- label left
int <- get
put (int + 1)
newRight <- label right
return (Branch newLeft (int, value) newRight)
run :: State' s a -> s -> (a, Counts)
run s ns = let (a, _, counts) = runState' s (ns, Counts 0 0 0 0) in (a, counts)
但是,当我运行测试用例时,我的结果是
(Branch (Branch Leaf (42,"B") Leaf) (42,"A") Leaf
, Counts {binds = 12, returns = 5, gets = 6, puts = 2})
Int 似乎根本没有更新。这很奇怪,因为作业的每个部分都有单独的测试用例,除此之外的一切都是正确的。无论如何,这里是 get 和 put 实现:
-- get :: State' s s
get = State' (\(s, counts) -> (s, s, counts <> oneGet))
-- put :: s -> State' s ()
put x = State' (\(x, counts) -> ((), x, counts <> onePut))
我在这里真的很茫然。我不知道为什么Ints 根本不受影响。非常感谢任何帮助。
【问题讨论】:
-
虽然你没有展示
instance Monad State'的实现,但我几乎可以保证它不满足单子定律;计算returns 和binds 不符合法律return x >>= f = f x和m >>= return = m。 (这根本与您的问题无关!)