Этот код взят из этой статьи.
Я был в состоянии следовать за ним до этой части.
module Test where
type State = Int
data ST a = S (State -> (a, State))
apply :: ST a -> State -> (a,State)
apply (S f) x = f x
fresh = S (\n -> (n, n+1))
instance Monad ST where
-- return :: a -> ST a
return x = S (\s -> (x,s))
-- (>>=) :: ST a -> (a -> ST b) -> ST b
st >>= f = S (\s -> let (x,s') = apply st s in apply (f x) s')
data Tree a = Leaf a | Node (Tree a) (Tree a) deriving (Show)
mlabel :: Tree a -> ST (Tree (a,Int))
-- THIS IS THE PART I DON'T UNDERSTAND:
mlabel (Leaf x) = do n <- fresh
return (Leaf (x,n))
mlabel (Node l r) = do l' <- mlabel l
r' <- mlabel r
return (Node l' r')
label t = fst (apply (mlabel t) 0)
tree = Node (Node (Leaf 'a') (Leaf 'b')) (Leaf 'c')
И label tree
производит:
Node (Node (Leaf ('a',0)) (Leaf ('b',1))) (Leaf ('c',2))
Я вижу, что оператор >>=
— это инструмент для «цепочки» функций, которые возвращают монады (или что-то в этом роде).
И хотя мне кажется, что я понимаю этот код, я не понимаю, как работает этот конкретный код.
В частности do n <- fresh
. Мы не передали никаких аргументов свежему, верно? Что в таком случае производит n <- fresh
? Абсолютно этого не понимаю. Может, это как-то связано с карри?