List 无法推断(a~[a])
我尝试编写一个函数,它获取子列表,反转子列表并返回串联的反转子列表。以下是我的尝试:List 无法推断(a~[a]),list,haskell,reverse,signature,type-deduction,List,Haskell,Reverse,Signature,Type Deduction,我尝试编写一个函数,它获取子列表,反转子列表并返回串联的反转子列表。以下是我的尝试: conrev :: Ord a => [[a]] -> [a] conrev [[]] = [] conrev [[a]] = reverse [a] conrev [(x:xs)] = reverse x ++ conrev [xs] main = putStrLn (show (conrev [[1,2],[],[3,4]])) 我得到这个错误: 3.hs:4:27: Could n
conrev :: Ord a => [[a]] -> [a]
conrev [[]] = []
conrev [[a]] = reverse [a]
conrev [(x:xs)] = reverse x ++ conrev [xs]
main = putStrLn (show (conrev [[1,2],[],[3,4]]))
我得到这个错误:
3.hs:4:27:
Could not deduce (a ~ [a])
from the context (Ord a)
bound by the type signature for conrev :: Ord a => [[a]] -> [a]
at 3.hs:1:11-31
`a' is a rigid type variable bound by
the type signature for conrev :: Ord a => [[a]] -> [a] at 3.hs:1:11
In the first argument of `reverse', namely `x'
In the first argument of `(++)', namely `reverse x'
In the expression: reverse x ++ conrev [xs]
我做错了什么?第二个问题是-类型签名是否更通用?我必须尽可能地编写泛型。您的第二个模式与您想要的不匹配,看起来您将类型的结构误认为是值的结构
[[a]]
作为一种类型意味着“某种类型的列表列表a
”
[[a]]
作为模式意味着“匹配包含单个列表的列表,该列表包含将绑定到名称a
的单个元素。”
编辑:
如果我明白你想做什么,中间的情况实际上是多余的。第三种情况将处理非空列表,第一种情况将处理空列表。为单例列表创建另一种情况是不必要的
编辑2:
第三个案例的实施还有一个问题
conrev :: Ord a => [[a]] -> [a]
conrev [(x:xs)] = reverse x ++ conrev [xs]
给定您看到的类型,x
必须是[a]
类型,xs
必须是[[a]]
类型。因此编写conrev[xs]
就是将类型为[[a]]
的值传递给conrev
。这就是您的类型错误的来源。您含蓄地声明了[a]
与a
的类型相同,方法是调用表达式中的convrev[xs]
conrev [(x:xs)] = reverse x ++ conrev [xs]
匹配一个包含单个元素的列表,它是一个非空列表x:xs
conrev :: Ord a => [[a]] -> [a]
列表x:xs
必须具有类型[a]
,因此x::a
现在,您调用reverse x
,这意味着x
必须是一个列表,x::[b]
,然后连接
reverse x :: [b]
与
由此可知,b
必须是与a
相同的类型。但之前已经确定,a~[b]
。因此,总的来说,等式要求a~[a]
如果您没有编写(不必要的)Ord a
约束,您会得到不那么不透明的约束
Couldn't construct infinite type a = [a]
错误
如果您删除了一些外部的[]
,那么您的实现将正常工作:
conrev :: Ord a => [[a]] -> [a]
conrev [] = []
conrev [a] = reverse a
conrev (x:xs) = reverse x ++ conrev xs
但更好的实施方式是
conrev = concat . map reverse
在我看来,您不需要Ord a=>这样:
conrev::[[]]->[]
?我遇到一个错误,希望对'[]'再加一个参数。
试试conrev::[[a]]->[a]无法将预期的类型'a'与实际的类型'[a]''a'是一个由conrev:[[a]->[a]的类型签名绑定的刚性类型变量在3.hs:1:11
这正是我想的。我有一个内部带有某种类型的子列表(在本例中,我推整数)在一个模式匹配中,当我只有一个子集时,我想处理这个情况。但是,您将类型语法与模式匹配的值相混淆。考虑您的中间情况在列表<代码> [[1,2] ] < /C>中,您得到模式匹配错误。在“代码> > [〔1〕]的情况下。a
绑定到1
,然后你做反向[1]
,这在技术上是正确的,但没有用。嗯……好吧,我删除了它。但我仍然有一个无法推断(a~[a])
的问题。
conrev = concat . map reverse