data Tree a = Nil | Node a (Tree a) (Tree a) deriving (Show, Eq) type Table a = [a] nNode:: (Eq a) => a -> Table a -> (Table a, Int) nNode x table = case (findIndex (== x) table) of Nothing -> (table ++ [x], length table) Just i -> (table, i)numTree' t = fst (runState (numberTree' t) []) where numberTree' :: Eq a => Tree a -> State (Table a) (Tree Int) numberTree' Nil = return Nil numberTree' (Node x t1 t2) = do num <- numberNode' x nt1 <- numberTree' t1 nt2 <- numberTree' t2 return (Node num nt1 nt2) numberNode' x = do table <- get (newTable, newPos) <- return (nNode x table) put newTable return newPos
Which reminds me that I want to point out my favorite example of the use of the Maybe monad so far. This may be obvious, but it was eye opening to me when I first saw it:
addM'' :: Maybe Int -> Maybe Int -> Maybe Int addM'' x y = do a <- x b <- y return (a + b)You could put all that on one line using ';' also. Here's the same code but without the use of the monad:
addM' :: Maybe Int -> Maybe Int -> Maybe Int addM' x y = if (isNothing x) || (isNothing y) then Nothing else Just ((fromJust x) + (fromJust y))
In general, I'm deep into the mode of hacking on State monads. I built a large function with them today and I'm deciding if I like the implementation or not. I definitely like the above example. I want to do some more exercises w/ state monads to get more intuition about when they're useful and when they're not useful.
deleteBy :: (a -> a -> Bool) -> a -> [a] -> [a]
When it could easily be
deleteBy :: (a -> Bool) -> [a] -> [a]
where that test element is curried. This makes it more general.
The second annoying thing about it is that I actually want the element it found to be returned to me also. I could do a two-pass version of this by combining several library functions, but I want a function like:
findAndDeleteBy :: (a->Bool) -> [a] -> (Maybe a, [a]) --or findAndDeleteBy :: (a->Bool) -> [a] -> Maybe (a,[a])
Here's my function:
-- |This function is like deleteBy, but also returns the element, if -- any. This is useful for locating an element in a list which fits a -- certain proporty, /f/, altering that element, and sticking it back -- into the remaining list. findAndDeleteBy :: (a -> Bool) -- ^An equality function, /f/ -> [a] -- ^A list to check out -> (Maybe a, [a]) -- ^Found elem, rest of the listfindAndDeleteBy f (h:t) = if f h -- Test the expression then (Just h, t) -- Found it else let (e, l) = findAndDeleteBy f t -- Try the rest in (e, h:l) -- Put it back together
findAndDeleteBy f [] = (Nothing, []) -- Base case
In other news:
New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.
Keep up with the latest Advogato features by reading the Advogato status blog.
If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!