Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 无法推断(a~[a])_List_Haskell_Reverse_Signature_Type Deduction - Fatal编程技术网

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