Вам не нужно преобразовывать 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
.
Что действительно нужно для функции 'label'? Я могу определить его как 'label = undefined', и он будет компилироваться, но это не значит, что вы хотите. – bheklilr
Он должен все чаще наклеивать дерево целыми числами, используя обход первого порядка в глубину. – maria