在Haskell中使用map和递归函数

时间:2013-02-01 03:39:42

标签: haskell recursion

所以我正在学习如何在Haskell中编程。

我希望看到的一件事是通过使用map并使用不使用列表推导而不使用map或任何其他高阶库函数的递归,为列表的每个元素添加1。

我认为看到两种实施方式都很酷。

2 个答案:

答案 0 :(得分:8)

如果您了解map的作用,那么我认为编写您打算做的事情并不困难。当您看到map

的类型时
*Main> :t map
map :: (a -> b) -> [a] -> [b]

因此它需要一个函数和一个列表,并在将该函数应用于列表的每个元素后返回另一个列表。因此,为了您的目的,为每个元素添加一个,您可以选择函数(+1)。所以

*Main> map (+1) [3,4,5,1,2]
[4,5,6,2,3]

如果您了解基本的haskell,现在定义自己的函数很容易。您可以查看map的来源以获取帮助。

map _ []     = []
map f (x:xs) = f x : map f xs

它为您提供了实现递归递增函数所需的所有帮助,如

add' [] = []
add' (x:xs) = (x+1) : add' xs

现在在ghci中尝试这个

*Main> add' [3,4,5,1,2]
[4,5,6,2,3]

答案 1 :(得分:3)

等式推理

Satvik很好地解释了递归版本,但是在列表推导版本中有一些非常有趣的东西。我们来看看。

add1 xs = [x + 1 | x <- xs]

列表推导的语法与Python非常相似,但它们实际上只是普通语言构造的语法糖 - do符号!

add1 xs = do x <- xs
             return (x + 1)

由于我们只是在列表monad上运行,我们可以去掉do符号

add1 xs = xs >>= \x -> return (x + 1)

然后应用一些转换

add1 xs = xs >>= return . (+1)
        = liftM (+1) xs
        = fmap  (+1) xs
        =  map  (+1) xs

我们回到了我们开始的地方。