我想要做的是对传递给stoline
的列表的每个元素(String
)应用stomap
函数。
stoline
的类型:stoline :: String -> [Obj]
。
这是我的代码:
stomap :: [[String]] -> [Obj]
stomap [[val]] = stoline val
stomap (val:vals) = map (\a -> stoline a) val ++ ...
传递给stomap
的数据示例:[["0","133","2"],["6","0","0"],["656","0","3"]]
。
错误:无法将预期类型Obj
与[Obj]
调用的返回类型中的实际类型stoline
匹配。
问题是map
函数返回一个列表(不应该!),但我真的不知道如何避免这个问题。
答案 0 :(得分:3)
您的第一个案例是不必要的,并且在您的第二个案例中出现错误:
map (\a -> stoline a) val ++ ...
val
此处为[String]
,因此map (\a -> stoline a) val
为[[Obj]]
。由于您使用++
将其与其他结果相结合,因此您的最终结果将是[[Obj]]
类型,而不是[Obj]
。
让我们重做它:
stomap :: [[String]] -> [Obj]
stomap lolos = concatMap (\los -> concatMap (\s -> stoline s) los) lolos
lolos
是字符串列表的列表,los
是字符串列表,s
是字符串。
我们在这里使用concatMap
,而不是普通的map
,因为我们要生成一个对象列表[Obj]
而不是对象列表列表的嵌套列表:{{1因为我们在输入中的每个[[[Obj]]]
上运行stoline
,我们需要在遍历String
时折叠该结构。
我们可以通过使其无点来清理上面的代码(使其更具有haskelly)。
lolos
与\s -> stoline s
相同,因此我们可以:
stoline
stomap lolos = concatMap (\los -> concatMap stoline los) lolos
与\los -> concatMap stoline los
相同,因此我们可以将其减少为:
concatMap stoline
我们可以放弃双方的争论,给我们:
stomap lolos = concatMap (concatMap stoline) lolos
起初看起来似乎难以辨认,但对于经验丰富的哈斯克勒来说,这可以比原始代码更清晰地读取 - 我很清楚,最后一个版本只是将stomap = concatMap (concatMap stoline)
的运行结果合并到一个列表中列表。