Tricky! This is a really good mechanism for comparing values with (==) at the last moment and only if necessary. Byt, why didn't you comment on this, at least with type information?
data Tree a = E | T (Tree a) a (Tree a) insert :: (Ord a) => a -> Tree a -> Tree a insert xt = const t `either` id $ insert' xt Nothing where -- insert' (insert_this) (into_this_empty_tree) (except_if_it_equals_this) (because_then_the_tree_is_Left_unchanged) insert' :: (Ord a) => a -> Tree a -> Maybe a -> Either (Tree a) (Tree a) insert' x E Nothing = Right (TE x E) insert' x E (Just v) | x==v = Left E | otherwise = Right (TE x E) -- insert' (insert_this) (into_this_nonempty_tree) ((anyway)) (recursive:if_it_branches_to_the_left_insert_it_there)
Why did you use Either if you threw out the left case and then use the copy? It would be more efficient if you did not save this copy to replace an equal tree and instead build an equal tree at all. Something like this...
insert' :: (Ord a) => a -> Tree a -> Maybe a -> Maybe (Tree a)
And then ... if you want to be really effective, do not create this parameter (perhaps a) to compare it afterwards.
The solution will look like this:
insert :: (Ord a) => a -> Tree a -> Tree a insert xt = fromMaybe t $ insert'1 xt where insert'1 :: (Ord a) => a -> Tree a -> Maybe (Tree a) insert'2 :: (Ord a) => a -> Tree a -> a -> Maybe (Tree a) insert'1 x E = Just (TE x E) insert'1 x (T lvr) | x<v = do l' <- insert'1 xl Just (T l' vr) | otherwise = do r' <- insert'2 xr Just (T lv r') insert'2 x E v = guard (x/=v) >> Just (TE x E) insert'2 xt _ = insert'1 xt
(EDIT:)
This instance is specified in Control.Monad.Error:
Error e => MonadError e (Either e)
That means (or String) you're probably looking.
insert :: (Ord a,MonadError String m) => a -> Tree a -> m (Tree a) insert xt = maybe (throwError "Error: element already in tree") return $ insert'1 xt where ...
comonad
source share