Ingannevole! È un ottimo meccanismo per confrontare i valori con (==) all'ultimo momento e solo se necessario. Perché non hai commentato almeno con le informazioni sul tipo?
data Tree a = E | T (Tree a) a (Tree a)
insert :: (Ord a) => a -> Tree a -> Tree a
insert x t = const t `either` id $ insert' x t 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 (T E x E)
insert' x E (Just v) | x==v = Left E
| otherwise = Right (T E x E)
-- insert' (insert_this) (into_this_nonempty_tree) ((anyway)) (recursive:if_it_branches_to_the_left_insert_it_there)
-- insert' (insert_this) (into_this_nonempty_tree) ((anyway)) (recursive:if_it_equals_or_branches_to_the_right_insert_it_there_except_if_the_right_branch_is_empty)
insert' x [email protected](T l v r) _ | x<v = (\l' -> T l' v r) `fmap` insert' x l Nothing
| otherwise = (\r' -> T l v r') `fmap` insert' x r (Just v)
Perché hai utilizzato Either, se hai gettato via la custodia sinistra e ne hai utilizzato una copia? Sarebbe più efficiente se non si tenesse quella copia per sostituire un albero uguale e invece di non costruire un albero uguale. In qualche modo come questo ...
insert' :: (Ord a) => a -> Tree a -> Maybe a -> Maybe (Tree a)
E poi ... se si vuole essere realmente efficace, non costruire che (forse a) il parametro solo per confrontarlo in seguito.
--insert'1 :: (Ord a) => a -> Tree a -> Nothin -> Maybe (Tree a)
--insert'2 :: (Ord a) => a -> Tree a -> Just a -> Maybe (Tree a)
insert'1 :: (Ord a) => a -> Tree a -> Maybe (Tree a)
insert'2 :: (Ord a) => a -> Tree a -> a -> Maybe (Tree a)
La soluzione sarebbe simile a questa:
insert :: (Ord a) => a -> Tree a -> Tree a
insert x t = fromMaybe t $ insert'1 x t
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 (T E x E)
insert'1 x (T l v r) | x<v = do l' <- insert'1 x l
Just (T l' v r)
| otherwise = do r' <- insert'2 x r
Just (T l v r')
insert'2 x E v = guard (x/=v) >> Just (T E x E)
insert'2 x t _ = insert'1 x t
(EDIT :)
In Control.Monad.L'errore è definito da questa istanza:
Error e => MonadError e (Either e)
Ciò significa che (o una stringa) è probabilmente quello che stai cercando.
insert :: (Ord a,MonadError String m) => a -> Tree a -> m (Tree a)
insert x t = maybe (throwError "Error: element already in tree") return $ insert'1 x t
where ...
prendere anche uno sguardo al [Gestione degli errori] capitolo (http://book.realworldhaskell.org/read/error-handling.html) nel libro _Real mondo Haskell_. –
Nitpick: se non si utilizza 'Left' per il caso di errore, non è possibile eseguire' Either' un functor, monad, ecc., Che è ciò che è più importante; non è solo * giusto * i due significati. –
@Antal S-Z: Personalmente, ho pensato che fosse solo perché [il lato sinistro è il male] (http://en.wiktionary.org/wiki/sinister#Etymology). –