Cofree
comonad is useful for iterating over partial functions in a way that is error polymorphic. Its coiter
resembles forM
-looping in monad errors, but it collects the received values in a clean / lazy way, and you only see the error at the end, down in the data structure.
For example, Cofree Identity
(no failure allowed!) Is an endless stream, while Cofree Maybe
is isomorphic to NonEmpty
, and Cofree (Either e) a
mostly (NonEmpty a, e)
(list of successful iterative values plus the error that occurs at the end).
Now I'm wondering what is the best way to evaluate the results, without specifically matching patterns on a single error monad. Retrieving all values is very easy thanks to the Foldable
instance (like toList
), but I'm not sure how best to get errors. You could use Foldable
to do this, just to get rid of the values and leave some of the error:
vals'n'err :: (Monad m, Foldable m) => Cofree ma -> (NonEmpty a, (m ())) vals'n'err (a :< q) = case toList q of [] -> (a:|[], const () <$> q) l -> first (pure a<>) $ foldr1 (\(bs,e) (cs,f) -> (bs<>cs, e>>f)) $ vals'n'err<$>l
but it's a bit of hacks. Is there a better solution?
source share