我正在为排序函数编写一个日志记录器,如下所示:
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.
3条答案
按热度按时间x6yk4ghg1#
朝正确的方向点头:
y
的类型是什么?bubble(x:ys)
的类型是什么?(:)
的类型是什么?答案:
(In这些答案,
a
与bubble :: (Ord a) => [a] -> Writer [String] [a]
中的a
相同。)y :: a
bubble(x:ys) :: Writer [String] [a]
bubble
是一个函数,bubble(x:ys)
是将bubble
应用于x:ys
的结果(:) :: b -> [b] -> [b]
:
为运算符;无论其第一操作数具有什么类型,其第二操作数必须具有类型“第一操作数具有什么类型的列表”,并且结果具有相同的列表类型。假设您已经给定
y
和bubble(x:ys)
作为:
的操作数,现在您能看出问题是什么吗?roqulrg32#
不幸的是,在这种情况下,
Writer w a
是WriterT w Identity a
的类型同义词,这使得编译器错误消息(通常信息量很大)更难解释,所以我的建议是简单地 * 完全忽略错误消息的内容 *,假装你是类型检查员。@dave4420提供了一个很好的提示,我想,我会补充说:不要删除
bubble
的类型声明-相反,请执行相反的操作:把bubble
分解成更小的helper函数,并为每个helper函数提供类型声明,这样问题所在就会变得更加清楚。我唯一的另一个提示是,这是编写一元代码的常见问题:记住哪些值是一元类型,哪些不是,以及何时“提升”。
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)
,因此您的代码应该是: