简体   繁体   中英

Converting a fold to a monadic fold haskell

I am having some difficulty converting a fold of a custom data type into a monadic fold. The idea is I should be able to fold with IO or Maybe using >>= . However, I'm getting errors I don't fully understand.

Here is my code:

data RTree a = Val a | Question String [RTree a] deriving (Show)

foldRT :: (a -> b) -> (String -> [b] -> b) -> RTree a -> b
foldRT v q (Val x) = v x 
foldRT v q (Question s xs) = q s $ map (foldRT v q) xs



foldRTM :: (Monad m) => (a -> m b) -> (String -> [b] -> m b) -> RTree a -> m b 
foldRTM v q t = foldRT (>>= v) q' (mon t)
   where q' s ls = mapM id ls >>= (\xs -> q s xs) 
         mon (Val x) = Val $ return x
         mon (Question s xs) = Question s (map return xs)

And here is the error message:

main.hs:14:36: error:
    • Couldn't match type ‘m’ with ‘RTree’
      ‘m’ is a rigid type variable bound by
        the type signature for:
          foldRTM :: forall (m :: * -> *) a b.
                     Monad m =>
                     (a -> m b) -> (String -> [b] -> m b) -> RTree a -> m b
        at main.hs:13:1-78
      Expected type: RTree (m a)
        Actual type: RTree (RTree a)
    • In the third argument of ‘foldRT’, namely ‘(mon t)’
      In the expression: foldRT (>>= v) q' (mon t)
      In an equation for ‘foldRTM’:
          foldRTM v q t
            = foldRT (>>= v) q' (mon t)
            where
                q' s ls = mapM id ls >>= (\ xs -> q s xs)
                mon (Val x) = Val $ return x
                mon (Question s xs) = Question s (map return xs)
    • Relevant bindings include
        q' :: String -> [m b] -> m b (bound at main.hs:15:10)
        q :: String -> [b] -> m b (bound at main.hs:14:11)
        v :: a -> m b (bound at main.hs:14:9)
        foldRTM :: (a -> m b) -> (String -> [b] -> m b) -> RTree a -> m b
          (bound at main.hs:14:1)
   |
14 | foldRTM v q t = foldRT (>>= v) q' (mon t)
   |                                    ^^^^^

The idea is that >>= v and q' as arguments to foldRT make its type...

(Monad m) :: (m a -> m b) -> (String -> [m b] -> m b) -> RTree m a -> m b

... but mapping getting the initial input of the tree into this form seems to not be working. I assume it's a stupid misunderstanding on my part.

Thanks!

The problem is from here:

     mon (Question s xs) = Question s (map return xs)

Where return has type of RTree a -> RTree (RTree a) .

You probably intended:

     mon (Question s xs) = Question s (map (fmap return) xs)

Also, foldRTM can be simplified to:

foldRTM :: (Monad m) => (a -> m b) -> (String -> [b] -> m b) -> RTree a -> m b 
foldRTM v q t = foldRT (>>= v) q' (return <$> t)
   where q' s ls = sequence ls >>= q s

If you make proper instance of Functor RTree :

instance Functor RTree where
    fmap f (Val x) = Val (f x)
    fmap f (Question s xs) = Question s (map (fmap f) xs)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM