1

我已经定义了一个表示树的新数据类型。我还实现了一个walk遍历树的所有元素的函数,该函数的功能版本是正确的,但不是他的一元版本walkM

module Hdot where
import qualified Data.ByteString.Char8 as B
import qualified Data.Map as Map

data RDoll a = Null | RDoll a [RDoll a] deriving (Show)    

test :: RDoll Int
test = RDoll 1 [RDoll 2 [Null], RDoll 3 [RDoll 4 [Null]]]

walk :: (a -> b) -> RDoll a -> [b]

walk f Null          = []
walk f (RDoll x rds) = ((f x): (concatMap (\x -> walk f x) rds))

walkM :: (Monad m) => (a -> m b) -> RDoll a -> m [b]
walkM f Null            = return []
walkM f (RDoll rd rdss) = do
  x <- f rd
  xs <- concatMap (walkM f) rdss
  return (x:xs) 

有类型错误

Couldn't match type `b' with `[b]'
...

有人能帮帮我吗!

感谢您的回复。

4

1 回答 1

7

通常,您应该提供完整的错误消息,因为它具有有价值的上下文:

A.hs:19:26:
    Could not deduce (m ~ [])
    from the context (Monad m)
      bound by the type signature for
                 walkM :: Monad m => (a -> m b) -> RDoll a -> m [b]
      at A.hs:(16,1)-(20,15)
      `m' is a rigid type variable bound by
          the type signature for
            walkM :: Monad m => (a -> m b) -> RDoll a -> m [b]
          at A.hs:16:1
    Expected type: [b]
      Actual type: m b
    Expected type: a -> [b]
      Actual type: a -> m b
    In the first argument of `walkM', namely `f'
    In the first argument of `concatMap', namely `(walkM f)'

[b]因此,值列表和操作列表之间存在一些混淆m b

可疑代码是您使用 concatMapwalkM递归运行。我认为您的意思是使用concatMapM(例如mapMconcat):

walkM :: (Monad m) => (a -> m b) -> RDoll a -> m [b]
walkM f Null            = return []
walkM f (RDoll rd rdss) = do
  x  <- f rd
  xs <- mapM (walkM f) rdss
  return (x:concat xs)

作为关于风格的说明,我会尝试写一些不同的东西。看看基础库中的玫瑰树。特别是不要定义walkand walkM,为 Functor、Monad 定义实例并重用现有的库函数。

于 2012-04-26T11:53:38.643 回答