Haskell递归映射函数

时间:2011-03-15 02:04:32

标签: haskell

为什么会抛出错误?

myTest :: Int -> [Int]
myTest a
    | a == 0          = []
    | otherwise  = x ++ map(myTest) x
    where x = [a-1]

我希望它会使列表从a变为1.相反,我得到错误:

couldn't match the expected type 'Int' against inferred type '[Int]'
in the first argument of 'map', namely '(myTest)'
in the second argument of '(++)', namely 'map (myTest) x'

这显然不是制作此列表的最佳方式,但它是我遇到的更复杂问题的简化版本。

我基本上有一个函数foo :: a -> [a],在结果列表中,我需要在每个元素上调用foo,将它扩展到另一个列表中。最后,我想要一个大的列表,其中每个元素都是基本情况。

我在Haskell相当新,所以我可能错过了一些相当基本的东西。

3 个答案:

答案 0 :(得分:3)

myTest的签名是Int -> [Int]

map的签名为(a -> b) -> [a] -> [b],由于myTest是第一个参数,因此(Int -> [Int]) -> [Int] -> [[Int]]

但是您的函数希望它生成[Int],而不是[[Int]]

编辑添加:我认为您想要的只是

myTest a
    | a == 0     = []
    | otherwise  = [a] ++ myTest (a-1)

虽然这可能不是你应该想要的东西(它比惯用的Haskell解决方案更重要),但是没有看到你的实际问题,这是一个简化,它&# 39;很难说。

答案 1 :(得分:2)

myTest :: Int -> [Int]

myTest 0 = []
myTest a = a : myTest (a-1)

答案 2 :(得分:2)

Else的答案更好,因为使用(:)代替(++)。在你的情况下,你可以使用,因为(:)在列表的前面添加一个元素,这就是你想要做的。

(++)是一个相对昂贵的操作,因为它复制了左手列表的脊柱。 (:)很便宜,因为它从不复制任何东西,它只是创建一个包含新头元素的新cons单元格。

如果可以的话,总是使用(:)代替(++)。

编辑:只是试图解释,因为Else没有发布他的代码的解释。