我是haskell的新手,我正在尝试创建一个函数,它将int乘以列表的每个元素。
示例:
mult 2 [2,4,6]
返回:
[4,8,12]
答案 0 :(得分:18)
将问题分解为概念性步骤:
您希望对列表的每个元素执行某些操作,这是map
函数提供的一般操作。使用它,您可以忽略该列表,并仅考虑您需要对单个元素执行的操作。
您想要将两个数字相乘。在函数的任何单独使用中,其中一个数字将是常量,因此我们可以给它一个名称作为函数的参数:mult x = ...
。现在我们可以将x
视为常量,只关心其他数字。
另一个数字不是常数,所以你需要一个函数,而不仅仅是一个简单的表达式。 Haskell为(*)
等中缀运算符提供了“运算符部分”,因此使用x
得到(x *)
。
退出最后几个步骤,您现在正在为x
提供一个名称,并创建一个您传递给map
的函数
mult x = map (x *)
......如果你愿意的话,你现在已经完成了。但是对于初学者来说,将列表作为一个明确的论点可能更清楚:
mult x ys = map (x *) ys
但两种形式都做同样的事情。
答案 1 :(得分:9)
我最初以一种略微不屑一顾的高尔夫风格回答了这个问题,让我们再试一次。我的目的是双重的:赎回自己为一个新人写一个快乐的睡眠剥夺的答案:-),并尝试暗示自由风格的点:
mult_l = map . (*)
该代码有什么作用?
以流水线方式思考它是有帮助的:
该代码需要(*)
并将其提供给map
。
(*)
的类型是什么?好吧,它是Num a => a -> a -> a
。这意味着它是什么?接受一个数字(称之为x
),然后给你另一个函数,这个函数将 - 如果给另一个数字(称之为y
) - 计算x
“次”{ {1}}。 (我在括号中加上“次”,因为y
是一个类型类...)
现在,您将使用Num
撰写 (*)
。 map
做了什么?好吧,让我们来看看它的类型:map
。所以现在,(a -> b) -> [a] -> [b]
将一个函数作为参数,并将该函数应用于列表的每个成员。
现在考虑一下合成的工作原理:map
。
如果有论据,请说2:
(f . g) x = f (g x)
真的是
mult_l 2
真的只是:
(map . (*)) 2
现在,map (* 2)
有两个参数,它需要一个函数(表示“你想让我做什么?”)并且需要一个列表(它表示“你想让我做什么” ?“)。 map
然后获取该列表中的每个项目,并将该函数应用于元素,指向。
这意味着如果你采取类似的行为:
map
然后map将获取列表,并查看第一个元素,然后将其乘以2,查看第二个元素等...
map (* 2) [1,2,3]
的类型是map . (*)
,因为它接收数字Num a => a -> [a] -> [a]
,然后输入更高的x
订单函数\x -> (* x)
到map
。
现在挑战问题(因为你是Haskell的新手),是如何写map
的?我会给你一个提示:
除此之外,您还可以获得map
的递归定义,以及相关的归纳原则。
你可能会困惑的另一件事是:为什么我必须写map . (*)
而不仅仅是map (*)
。如果你想一段时间,你可能会对point free style
答案 2 :(得分:6)
由于没有人谈论列表理解,所以只是告诉另一种方法。
mult x ys = [i*x | i <- ys]