简体   繁体   English

Haskell Monad.Writer

[英]Haskell Monad.Writer

I am writing a logger for a sorting function like this:我正在为这样的排序功能编写一个记录器:

bubble :: (Ord a) => [a] -> Writer [String] [a]
bubble (x:y:ys)  
        | x > y = do
                tell [show x ++ " why does this not work"]
                y:bubble(x:ys)
        | otherwise = do
                tell [show y ++ " is a number"] 
                x:bubble(y:ys)
bubble [x] = do 
            tell ["nothing works"]
            return [x] 

but i get this error:但我收到此错误:

 Couldn't match expected type `WriterT
                                    [String] Data.Functor.Identity.Identity [a]'
                with actual type `[a0]'
    In a stmt of a 'do' block: y : bubble (x : ys)
    In the expression:
      do { tell [show x ++ " why does this not work"];
           y : bubble (x : ys) }
    In an equation for `bubble':
        bubble (x : y : ys)
          | x > y
          = do { tell [show x ++ " why does this not work"];
                 y : bubble (x : ys) }
          | otherwise
          = do { tell [show y ++ " is a number"];
                 x : bubble (y : ys) }
Failed, modules loaded: none.

I have read this error message word for word but I am not any closer to what the problem is?我已经逐字逐句地阅读了这条错误消息,但我还没有更接近问题所在? I tried compiling with out the deceleration, for a fresh set of errors like this:我尝试在不减速的情况下进行编译,但出现了一组新的错误,如下所示:

q.hs:21:17:
    No instance for (MonadWriter [[Char]] [])
      arising from a use of `tell'
    Possible fix:
      add an instance declaration for (MonadWriter [[Char]] [])
    In a stmt of a 'do' block:
      tell [show x ++ " why does this not work"]
    In the expression:
      do { tell [show x ++ " why does this not work"];
           y : bubble (x : ys) }
    In an equation for `bubble':
        bubble (x : y : ys)
          | x > y
          = do { tell [show x ++ " why does this not work"];
                 y : bubble (x : ys) }
          | otherwise
          = do { tell [show y ++ " is a number"];
                 x : bubble (y : ys) }
Failed, modules loaded: none.

A nod in the right direction: 向正确的方向点头:

  1. What is the type of y ? y的类型是什么?
  2. What is the type of bubble(x:ys) ? bubble(x:ys)的类型是什么?
  3. What is the type of (:) ? (:)是什么类型?

Answers: 答案:

(In these answers, a is the same a as in bubble :: (Ord a) => [a] -> Writer [String] [a] .) (在这些答案, a是同a作为bubble :: (Ord a) => [a] -> Writer [String] [a]

  1. y :: a
  2. bubble(x:ys) :: Writer [String] [a]
    • bubble is a function, bubble(x:ys) is the result of applying bubble to x:ys bubble是一个函数, bubble(x:ys)是对x:ys应用bubble的结果
  3. (:) :: b -> [b] -> [b]
    • : is an operator; :是运算符; whatever type its first operand has, its second operand must have the type "list of whatever type the first operand has", and the result has that same list type. 无论第一个操作数具有哪种类型,其第二个操作数都必须具有“第一个操作数具有的任何类型的列表”类型,并且结果具有相同的列表类型。

Given that you have given y and bubble(x:ys) as the operands to : , can you see now what the problem is? 既然你已经给ybubble(x:ys)作为操作数来: ,你能看到现在的问题是什么?

It's somewhat unfortunate, in cases like these, that Writer wa is a type synonym for WriterT w Identity a . 在这种情况下, Writer waWriterT w Identity a的类型同义词是有些不幸WriterT w Identity a It makes the compiler error messages (which are normally very informative) much harder to interpret. 这使编译器错误消息(通常非常有用)更加难以解释。 So my suggestion here is to simply ignore the content of the error message entirely and pretend you're the type checker. 因此,我的建议是完全忽略错误消息的内容,并假装您是类型检查器。

@dave4420 provided a very good hint, I think. 我认为@ dave4420提供了很好的提示。 I'll add to that by saying: don't remove the type declaration for bubble - instead, go the opposite way: break bubble down into smaller helper functions, providing type declarations for each one. 我要说的是:不要删除bubble的类型声明-相反,请按照相反的方式:将bubble分解为较小的辅助函数,为每个函数提供类型声明。 Then it should become much more clear where your problem lies. 然后应该更加清楚您的问题所在。

My only other hint is that this is a common issue with writing monadic code: remembering which values are of monadic type, which aren't, and when to "lift." 我唯一的另一个暗示是,这是编写单子代码的常见问题:记住哪些值属于单子类型,哪些不是,何时“提升”。

The message讯息

Couldn't match expected type `WriterT [String] Data.Functor.Identity.Identity [a]' with actual type `[a0]' In a stmt of a 'do' block: y: bubble (x: ys)无法将预期类型“WriterT [String] Data.Functor.Identity.Identity [a]”与实际类型“[a0]”匹配在“do”块的 stmt 中:y: bubble (x: ys)

Is referring to the fact that y:bubble(x:ys) has a type of [a] and bubble 's is supposed to be a Writer [String] [a] .指的是y:bubble(x:ys)的类型是[a]bubble的应该是Writer [String] [a] Ie the types do not match .类型不匹配

y:bubble(x:ys) is just a list, but what you need it to be is a list embedded within your writer monad. y:bubble(x:ys)只是一个列表,但您需要的是嵌入在您的 writer monad 中的列表。 In order to embed it as the result of your writer monad you need to use return .为了将它作为你的 writer monad 的结果嵌入,你需要使用return

  • y:bubble(x:ys) has a type of [a] y:bubble(x:ys)的类型是[a]
  • return $ y:bubble(x:ys) has a type of Writer [String] [a] return $ y:bubble(x:ys)的类型为Writer [String] [a]

The same applies to x:bubble(y:ys) .这同样适用于x:bubble(y:ys) Thus your code ought to be:因此你的代码应该是:

bubble :: (Ord a) => [a] -> Writer [String] [a]
bubble (x:y:ys)  
        | x > y = do
                tell [show x ++ " why does this not work"]
                return $ y:bubble(x:ys)
        | otherwise = do
                tell [show y ++ " is a number"] 
                return $ x:bubble(y:ys)
bubble [x] = do 
            tell ["nothing works"]
            return [x] 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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