我有以下类型:
data Tree a = Branch (Tree a) a (Tree a) | Leaf
deriving (Eq, Ord, Show)
newtype State' s a = State' { runState' :: (s, Counts) -> (a, s, Counts) }
使用这些实例:
instance Monad (State' s)
instance MonadState (State' s) s
我需要制作一个功能
label :: MonadState m Int => Tree a -> m (Tree (Int, a))
但我不知道如何将树转换为State'
。
答案 0 :(得分:1)
您无需将Tree
转换为有状态值,您需要在标记过程的每个阶段使用Int
的有状态值。为此,你可能会从
getLabelAndIncr :: MonadState m Int => m Int
getLabelAndIncr = do
current <- get
put $ current + 1
return current
然后在label
函数中,您可以执行类似
label :: MonadState m Int => Tree a -> m (Tree (Int, a))
label Leaf = return Leaf
label (Branch left node right) = do
l <- getLabelAndIncr
let newNode = (l, node)
newLeft <- ???
newRight <- ???
return $ Branch newLeft newNode newRight
你必须弄明白???
中的内容,我不会为你解决所有问题,但这应该是一个相当简单的练习。这里发生的是getLabelAndIncr
获取要使用的当前标签值,然后将该值增加到该状态。然后构造一个用该标签标记的新节点值,左右分支获取它们的标签,并返回一个现在有标签的新树。每次状态的类型保持不变,由MonadState m Int
确定,m
表示Int
是一个有状态的monad,总是的状态值为{{ 1}}。
答案 1 :(得分:0)
您不必将Tree
转换为状态,类型签名的m (Tree (Int, a))
部分仅表示结果为Tree
,其中包含{ {1}}和Int
s,它本身位于州monad中。它甚至不必是a
monad。