Edit II: A, okay: I did not understand how a and b are related in the definition of eval! Now I do it. If anyone is interested, this is a chart that tracks a and b. I am quite a big fan of diagrams. The drawing arrows really improved my Haskell, I swear.
Call chart eval (PDF)
Sometimes I feel very tight.
In Wadlerβs section β Monads for Functional Programmingβ , he introduces the state into a simple evaluation function. The original (non-monodic) function monitors the state using a series of let expressions, and is easy to follow:
data Term = Con Int | Div Term Term deriving (Eq, Show) type M a = State -> (a, State) type State = Int eval' :: Term -> M Int eval' (Con a) x = (a, x) eval' (Div tu) x = let (a, y) = eval' tx in let (b, z) = eval' uy in (a `div` b, z + 1)
The definitions of unit and binding for a monadic evaluator are similar simply:
unit :: a -> M a unit a = \x -> (a, x) (>>=) :: M a -> (a -> M b) -> M b m >>= k = \x -> let (a, y) = mx in let (b, z) = kay in (b, z)
Here (β =) takes the monadic value m :: M a, the function k :: a β M b and displays the monadic value M b. The value of m depends on the value selected for x in the lambda expression.
Wadler then introduces the tick function:
tick :: M () tick = \x -> ((), x + 1)
Again, straight. However, it is not easy how to combine these functions together to create an evaluation function that returns the number of division operators to execute. In particular, I do not understand:
(1) How the tick is carried out. For example, the following valid function call:
(tick >>= \() -> unit (div 4 2)) 0 ~> (2, 1)
However, I cannot correctly evaluate it manually (indicating that I misunderstand something). In particular: (a) The result of evaluating a tick at 0 is ((), 0), since the lambda expression takes ()? (b) If a is the first element of the pair returned by calling tick at 0, how is the unit evaluated?
(2) How to combine tick and block to track the number of split statements to execute. While an ambiguous appraiser is not problematic, using bind confuses me.
Edit: Thanks, everyone. I think my misunderstanding was the role of the lambda expression, '() β unit (div 4 2)'. If I understand correctly,
(tick >>= (\() -> unit (div mn)) x
expands to
(\x -> let (a, y) = tick x in let (b, z) = (\() -> unit (div mn) ay) in (b, z)) x
When 'a' is applied to '() β unit (div mn) y', no "bottom line" is obtained. The same effect can be achieved by associating any variable with the lambda operator and substituting a value for it. In this case, the universality of the binding lies in the fact that any value of M a can be transferred to it. As noted, the value of M a is a calculation, for example, "eval". Consequently:
eval (Con a) = unit a eval (Div tu) = eval t >>= (\a -> eval u >>= (\b -> tick >>= (\c -> unit (a `div` b))))
If I understand correctly, 'eval t' is replaced with m and the rest of the expression, the function
'(\a -> eval u >>= (\b -> tick >>= (\c -> unit (a `div` b))))'
is replaced by k. The result of the evaluation "eval t" is related to (a, y), and the result of the estimate k is related to (b, z). I have ways to go, but that makes it a little easier. Thanks.