在GHCi中编译:
splitLines:: String -> [[String]]
splitLines splitLinesStr = splitWords (lines splitLinesStr)
splitWords:: [String] -> [[String]]
splitWords splitWordList = tupleNums (map words splitWordList)
tupleNums :: (Enum a, Num a) => [b] -> [(a, b)]
tupleNums tupleNumList = zip [1..] tupleNumList
给出以下错误消息:
Couldn't match type ‘(Integer, [String])’ with ‘[String]’
Expected type: [[String]]
Actual type: [(Integer, [String])]
In the expression: tupleNums (map words splitWordList)
In an equation for ‘splitWords’:
splitWords splitWordList = tupleNums (map words splitWordList)
有人知道如何修复此类错误吗?我是初学者所以指针很有帮助。
答案 0 :(得分:4)
与大多数类型错误一样,错误可以在调用者或被调用者,在这种情况下,我怀疑它与< EM>呼叫者
最可能的解释是,您不必致电tupleNums
:
splitLines:: String -> [[String]]
splitLines splitLinesStr = splitWords (lines splitLinesStr)
splitWords:: [String] -> [[String]]
splitWords splitWordList = map words splitWordList
这很简单,你不会附加任何&#34;行号&#34; (?)你的话。
另一种可能性是,当您开始添加行号时,您无法更新 splitLines
和splitWords
的类型:
splitLines:: (Enum a, Num a) => String -> [(a,[String])]
splitLines splitLinesStr = splitWords (lines splitLinesStr)
splitWords:: (Enum a, Num a) => [String] -> [(a,[String])]
splitWords splitWordList = tupleNums (map words splitWordList)
tupleNums :: (Enum a, Num a) => [b] -> [(a, b)]
tupleNums tupleNumList = zip [1..] tupleNumList
修改强>
如何操纵类型签名?我们只讨论splitWords
,因为splitLines
的情况是等价的。首先让我们来看看表达式:
tupleNums (map words splitWordList)
类型:
splitWordList :: String
(输入); words :: String -> [String]
(图书馆); map :: (a -> b) -> [a] -> [b]
(图书馆); tupleNums :: (Enum c, Num c) => [d] -> [(c, d)]
(已定义)。由于名称冲突,我已将a
和b
tupleNames
重命名为c
和d
。现在,Haskell如何解释这些类型?
必须填写a
的{{1}}和b
。现在因为map
的第一个参数类型为map
和a -> b
,这意味着words :: String -> [String]
和a = String
。通过这样做,我们使用的b = [String]
(可以这么说)折叠为:
map
现在,当我们在map words :: [String] -> [[String]]
上调用此函数时,它会进一步折叠为:
splitWordList
现在,此表达式的结果将是map words splitWordList :: [[String]]
s。
Haskell还需要猜测String
的类型。由于它具有签名:tupleNums
并将(Enum c, Num c) => [d] -> [(c, d)]
作为第一个参数,这意味着map words splitWordList :: [[String]]
(思维d = [String]
不是c
)。所以这崩溃了:
String
它不能/不应该推理tupleNums (map words splitWordList) :: (Enum c, Num c) => [[String]] -> [(c, String)]
,因为目标是尽可能保持函数的通用性。
注意(类型推断):但是请注意,Haskell(大多数情况下)不需要给出类型。它有一个类型推断系统,可以生成最通用的类型签名。如果您向编译器提供此文件:
c
您可以使用以下命令查询Haskell已解决的类型:
splitLines splitLinesStr = splitWords (lines splitLinesStr) splitWords splitWordList = tupleNums (map words splitWordList) tupleNums tupleNumList = zip [1..] tupleNumList
如果您所说的从类型角度来看没有任何意义,那么它将无法编译。类型可用于自己跟踪项目。有一些(GHC)语言扩展可以使类型系统无法找到最通用的类型或让它陷入无限循环。