【问题标题】:Converting a fold to a monadic fold haskell将折叠转换为一元折叠haskell
【发布时间】:2018-03-11 01:45:13
【问题描述】:

我在将自定义数据类型的折叠转换为单子折叠时遇到了一些困难。这个想法是我应该能够使用>>= 折叠IOMaybe。但是,我遇到了一些我不完全理解的错误。

这是我的代码:

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)

这是错误信息:

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)
   |                                    ^^^^^

这个想法是 >>= vq' 作为 foldRT 的参数使其类型...

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

...但是将树的初始输入映射到这种形式似乎不起作用。我认为这是我的一个愚蠢的误解。

谢谢!

【问题讨论】:

    标签: haskell monads fold


    【解决方案1】:

    问题出在:

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

    return 的类型为 RTree a -> RTree (RTree a)

    你可能打算:

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

    另外,foldRTM 可以简化为:

    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
    

    如果你创建了 Functor RTree 的正确实例:

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

    【讨论】:

    • 非常感谢!你能告诉我我为什么要这么做吗?如果没有也没问题
    猜你喜欢
    • 2015-08-30
    • 2020-09-15
    • 2015-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多