如何将数据类型转换为MonadState

时间:2014-10-17 16:39:29

标签: haskell binary-tree monads

我有以下类型:

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'

2 个答案:

答案 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。