
Andrea Rossato wrote:
this is what I'm trying to do, sort of: turn the code at the button into the do-notation.[1]
type MSO a = State -> (a, State, Output)
mkMSO :: a -> MSO a mkMSO a = \s -> (a, s, "")
bindMSO :: MSO a -> (a -> MSO b) -> MSO b bindMSO m f = \x -> let (a, y, s1) = m x in let (b, z, s2) = f a y in (b, z, s1 ++ s2)
In principle (might need glasgow-exts), you could go ahead and declare instance Monad MSO where return = mkMSO (>>=) = bindMSO This doesn't work, because MSO ist just a function (the top type constructor is (->)), and there is already a Monad instance for (->). You could activate all sorts of extensions (glasgow-exts and overlapping-instances at the very least) to allow the overlap, but I guess, this will only serve to confuse first the type checker and later you. Instead, you have to make clear that MSO is represented as a function, but is to be treated as different, and that's what 'newtype' is for. After wrapping a function in a newtype, it is something else, so it has to be unwrapped before it can be used as a function again:
newtype MSO a = MSO { unMSO :: State -> (a, State, Output) }
mkMSO :: a -> MSO a mkMSO a = MSO (\s -> (a, s, ""))
bindMSO :: MSO a -> (a -> MSO b) -> MSO b bindMSO m f = MSO (\x -> let (a, y, s1) = unMSO m x in let (b, z, s2) = unMSO (f a) y in (b, z, s1 ++ s2))
and now MSO can no longer be confused with other functions and you can declare your Monad instance:
instance Monad MSO where return = mkMSO (>>=) = bindMSO
-- To be tested with: -- evalMSO (Add (Con 6) (Add (Con 16) (Add (Con 20) (Con 12)))) 0
Now this won't work, since evalMSO produces an MSO, not a function. You have to unwrap it to use the function:
unMSO (evalMSO (Add (Con 6) (Add (Con 16) (Add (Con 20) (Con 12))))) 0
Udo. -- From the MFC source: // according to the Win98 docs, this should be 1 // according to the WinNT docs, this should be 2 // they are both wrong!