Haskell映射函数实现问题

Haskell映射函数实现问题,haskell,map,compiler-errors,concatenation,Haskell,Map,Compiler Errors,Concatenation,我刚开始学习Haskell,在适应该语言方面遇到了困难,例如在执行map时遇到了困难,尤其是在尝试执行类似于下面示例中的操作时 rotate :: Dimensions -> imgBlock -> [(imgBlock,Int)] rotate d ((p, pix), s, t) = zip [((p, f pix), s, t) | f <- transformate (fst d)] [0..7] makeAllRotations :: Dimensions

我刚开始学习Haskell,在适应该语言方面遇到了困难,例如在执行
map
时遇到了困难,尤其是在尝试执行类似于下面示例中的操作时

rotate :: Dimensions ->  imgBlock -> [(imgBlock,Int)]
rotate d ((p, pix), s, t) 
  = zip [((p, f pix), s, t) | f <- transformate (fst d)] [0..7]

makeAllRotations :: Dimensions -> [imgBlock] -> [(imgBlock,Int)]
makeAllRotations d ib = map concat (rotate d ib)              //Error points Here
这是我犯的错误之一

asdf.hs:73:30:
    Couldn't match expected type `(imgBlock, Int)'
                with actual type `[a0]'
    Expected type: [[a0]] -> (imgBlock, Int)
      Actual type: [[a0]] -> [a0]
    In the first argument of `map', namely `concat'
    In the expression: map concat (rotate d ib)
我发现自己在尝试适应这种新的编程“范式”时非常沮丧,因为我所做的大部分事情都是通过反复试验来完成的。显然,我没有正确理解
map
,尽管我已经阅读了相关文档,但所有示例都显示在控制台中,比如
map(2+[1,2,3]
,在函数中使用它们时就不那么多了


我可以得到一些关于我的
map
实现哪里出错的提示吗。Thks

找到问题的最佳方法是查看以下类型:

rotate :: Dimensions -> ImgBlock -> [(ImgBlock,Int)]
makeAllRotations :: Dimensions -> [ImgBlock] -> [(ImgBlock,Int)]
map :: (a -> b) -> [a] -> [b]
concat :: [[a]] -> [a]
map函数正在尝试对rotate返回的列表中的每个(ImgBlock,Int)对调用concat。但是concat希望得到一个嵌套列表作为其参数。但是帮助我解决这个问题的一件大事是查看
rotatedib
。要旋转的第二个参数是ImgBlock,但在该上下文中ib::[ImgBlock]。当需要单个项目时,无法传入列表。但这就是map函数的作用。它允许您使用一个接受单个项的函数(上面类型签名中的“a”),并在您有[a]时使用该函数。我怀疑你想要的是这样的:

makeAllRotations d ib = concat $ map (rotate d) ib

因为rotate返回一个列表,
map(rotate d)ib
返回一个列表列表,它非常适合作为concat函数的第一个参数。

一个好主意是命名中间值,使用
where
语法,并为所有内容提供类型签名。这迫使你思考(反对反复试验)。不要对哈斯克尔失去希望!如果你愿意调整你的思维模式,你会得到很好的回报我赞同塔拉什的建议。在学习Haskell时,尽可能多地将类型指定给中间步骤非常有帮助:如果没有其他步骤,它会澄清您的想法。最终,您可以省略越来越多的类型,让编译器推断它们。这里不是
映射concat(rotate d ib)
如果您编写了
映射concat x,其中x::…
并试图通过x的类型进行推理,您可能已经找到了错误。或者学着解释错误:这是说
concat
是实际类型
[[a0]]->[a0]->[a0]
(你知道),它不能与类型
[[a0]]->(imgBlock,Int)
@Tarrasch,@shrevatsar匹配;伙计们非常感谢你们的建议和支持,在这样的挫折时刻,这真的意味着整个世界。我当然会把你的建议付诸实践,因为我显然需要找到一种方法来适应像haskell这样的声明性语言。再一次感谢它,我不得不说我不熟悉
$
操作符,但我想我现在已经熟悉了;)将一个列表返回函数映射到一个列表上的结果连接起来是很常见的,它有自己的函数
concatMap
makeAllRotations d ib=concatMap(rotate d)ib
,或者无点:
makeAllRotations=concatMap。旋转
makeAllRotations d ib = concat $ map (rotate d) ib