At 20:40 04/06/03 +0200, Tomasz Zielonka wrote:
> > > I'm trying to figure if there's any way I can use (say) monads to collect
> > > values from a Functor.
> > >
> > > For example, suppose I have a tree of some values that supports fmap, is
> > > there any way I can use the fmap function to collect a list of all the node
> > > values?
> >
> > No, you need a fold to do that.
> Or a variant of Functor constructor class that I have proposed some time > ago on comp.lang.functional: > > class FunctorM t where > fmapM :: Monad m => (a -> m b) -> (t a -> m (t b)) > fmapM_ :: Monad m => (a -> m b) -> (t a -> m ()) > fmapM_ f t = fmapM f t >> return () > > instance FunctorM [] where > fmapM = mapM > fmapM_ = mapM_
I've done a little playing with this, which seems to work on a small scale, and am just wanting to check if I am properly understanding your idea...
'Arc' is a small part of a data structure I am playing with, which is currently a Functor. I've made this an instance of FunctorM, defining fmapM which has some recognizable similarity with fmap. Finally, there's a monad type CollectNodes using Control.Monad.State and constructor function mungeNode to actually apply the transformation and collect results.
It seems to work -- is this roughly what you envisaged?
[[ -- spike-FunctorM.hs
import Control.Monad.State
class FunctorM t where
fmapM :: Monad m => (a -> m b) -> (t a -> m (t b))
fmapM_ :: Monad m => (a -> m b) -> (t a -> m ())
fmapM_ f t = fmapM f t >> return ()data Arc lb = Arc { asubj, apred, aobj :: lb }
deriving (Eq, Show)instance Functor Arc where
fmap f (Arc s p o) = Arc (f s) (f p) (f o)instance FunctorM Arc where
-- fmapM :: (lb -> m l2) -> Arc lb -> m (Arc l2)
fmapM f (Arc s p o) =
do { s' <- f s
; p' <- f p
; o' <- f o
; return $ Arc s' p' o'
}-- CollectNodes a b is a state transformer on a state of
-- type '[a]', which additionally returns a value of type 'b'.
type CollectNodes a b = State [a] b
-- constructor State { runState :: (s -> (a, s)) }
-- runState :: State s a -> s -> (a, s)
-- evalState :: State s a -> s -> a
-- execState :: State s a -> s -> s
-- mapState :: ((a, s) -> (b, s)) -> State s a -> State s b
-- withState :: (s -> s) -> State s a -> State s a
-- instance MonadState s (State s)
-- get :: m s -- (CollectNodes a b) [a]
-- put :: s -> m ()
-- modify :: (MonadState s m) => (s -> s) -> m ()
-- gets :: (MonadState s m) => (s -> a) -> m amungeNode :: lb -> CollectNodes lb (Maybe lb)
mungeNode lab =
do { modify (lab:) -- accumulate labels
; return (Just lab) -- return modified label
}a1 = Arc "s1" "p1" "o1"
r1 = runState ( fmapM mungeNode a1 ) [] ]]
I think, but haven't worked out the details, that one could define fmap in terms of fmapM. (I read somewhere about an identity Monad, but can't recall the reference -- I think that might do it.)
I'm also harbouring a suspiscion that this FunctorM framework might be subsumed by gmap and friends, but I'll leave that for another day.
#g
------------------- Graham Klyne <[EMAIL PROTECTED]> PGP: 0FAA 69FF C083 000B A2E9 A131 01B9 1C7A DBCA CB5E
_______________________________________________ Haskell-Cafe mailing list [EMAIL PROTECTED] http://www.haskell.org/mailman/listinfo/haskell-cafe
