haskell ·莫纳德,作家

ufj5ltwl  于 2022-12-19  发布在  其他
关注(0)|答案(3)|浏览(126)

我正在为排序函数编写一个日志记录器,如下所示:

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]

但我得到这个错误:

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.

我已经逐字阅读了这个错误信息,但我并没有更接近问题所在?我尝试在不使用减速的情况下进行编译,得到了一组新的错误,如下所示:

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.
x6yk4ghg

x6yk4ghg1#

朝正确的方向点头:

  1. y的类型是什么?
  2. bubble(x:ys)的类型是什么?
  3. (:)的类型是什么?
    答案:
    (In这些答案,abubble :: (Ord a) => [a] -> Writer [String] [a]中的a相同。)
  4. y :: a
  • bubble(x:ys) :: Writer [String] [a]
  • bubble是一个函数,bubble(x:ys)是将bubble应用于x:ys的结果
  • (:) :: b -> [b] -> [b]
  • :为运算符;无论其第一操作数具有什么类型,其第二操作数必须具有类型“第一操作数具有什么类型的列表”,并且结果具有相同的列表类型。

假设您已经给定ybubble(x:ys)作为:的操作数,现在您能看出问题是什么吗?

roqulrg3

roqulrg32#

不幸的是,在这种情况下,Writer w aWriterT w Identity a的类型同义词,这使得编译器错误消息(通常信息量很大)更难解释,所以我的建议是简单地 * 完全忽略错误消息的内容 *,假装你是类型检查员。
@dave4420提供了一个很好的提示,我想,我会补充说:不要删除bubble的类型声明-相反,请执行相反的操作:把bubble分解成更小的helper函数,并为每个helper函数提供类型声明,这样问题所在就会变得更加清楚。
我唯一的另一个提示是,这是编写一元代码的常见问题:记住哪些值是一元类型,哪些不是,以及何时“提升”。

enyaitl3

enyaitl33#

该消息
在'do'区块的stmt中,无法将预期类型'WriterT [String] Data.Functor.Identity.Identity [a]'与实际类型'[a0]'相符:y:气泡(x:年)
是指y:bubble(x:ys)的类型为[a],而bubble的类型应该为Writer [String] [a]。即,* 类型不匹配 *。
y:bubble(x:ys)只是一个列表,但是你需要它是一个嵌入到你的writer单子中的列表,为了把它作为你的writer单子的结果嵌入,你需要使用return

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

这同样适用于x:bubble(y:ys),因此您的代码应该是:

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]

相关问题