将折叠转换为一元折叠 haskell
Converting a fold to a monadic fold haskell
我在将自定义数据类型的折叠转换为单子折叠时遇到了一些困难。我的想法是我应该能够使用 >>=
和 IO
或 Maybe
弃牌。但是,我遇到了我不完全理解的错误。
这是我的代码:
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)
| ^^^^^
想法是 >>= v
和 q'
作为 foldRT
的参数使其类型...
(Monad m) :: (m a -> m b) -> (String -> [m b] -> m b) -> RTree m a -> m b
...但是将树的初始输入映射到这种形式似乎不起作用。我认为这是我的一个愚蠢的误解。
谢谢!
问题出在这里:
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)
我在将自定义数据类型的折叠转换为单子折叠时遇到了一些困难。我的想法是我应该能够使用 >>=
和 IO
或 Maybe
弃牌。但是,我遇到了我不完全理解的错误。
这是我的代码:
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)
| ^^^^^
想法是 >>= v
和 q'
作为 foldRT
的参数使其类型...
(Monad m) :: (m a -> m b) -> (String -> [m b] -> m b) -> RTree m a -> m b
...但是将树的初始输入映射到这种形式似乎不起作用。我认为这是我的一个愚蠢的误解。
谢谢!
问题出在这里:
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)