问题描述
我正在尝试学习 SML(为了完全透明,这是为考试做准备(考试尚未开始)),我一直在努力研究的一个领域是更高级的函数,例如 map 和 foldl/r。我知道它们用于在 oop 语言中使用 for 循环的情况(我认为)。我正在努力解决的是折叠或地图功能中的每个部分正在做什么。这里有一些例子,如果有人可以分解它们,我会非常感激
fun cubiclist L = map (fn x=> x*x*x) L;
fun min (x::xs) = foldr (fn (a,b) => if (a < b) then a else b) x xs;
因此,如果我可以分解我看到的部分并突出显示我正在努力处理的部分,我相信这会有所帮助。
很明显,你马上就知道了函数的名称和传入的参数,但我在这方面的一个问题是为什么我们只是将一个变量传递给cubiclist,但对于min,我们传入(x ::xs)?是不是因为地图功能会自动将功能应用到地图中的每个部分?此外,折叠函数通常采用 x::xs 参数,而 map 仅采用变量吗?
然后我们有高阶函数和匿名函数以及我们想要应用于列表中每个元素的逻辑/操作。但是我不太确定为 foldr 匿名函数传入的参数。我知道我们正在尝试捕获列表中的最低元素,then a else b
返回 a 或 b 以与列表中的其他元素进行比较。我很确定它们在未来的比较中被忽略并被视为 a
但我们从哪里得到以下 b
?我们在哪里说 b
是列表中的下一个元素?
然后我真的不明白和不知道的部分是相应函数末尾的L;
和x xs;
。他们为什么在那里?他们在做什么?他们的目的是什么?这只是语法还是他们在那里的真正目的,并不是说语法不是目的或正当理由,但他们真的做了什么吗?是否可以用其他可以提供不同答案的变量来更改这些变量?
非常感谢任何帮助/解释。
解决方法
map
接受一个函数和一个列表并生成一个新列表。
在map (fn x=> x*x*x) L
中,函数是fn x=> x*x*x
,L
是列表。
此列表与 cubiclist
的参数相同。
foldr
接受一个函数、一个初始值和一个列表并产生某种值。
在foldr (fn (a,b) => if (a < b) then a else b) x xs
中,函数为fn (a,b) => if (a < b) then a else b
,初始值为x
,列表为xs
。x
和 xs
通过模式匹配赋予函数; x
是参数的头部,xs
是它的尾部。
(因此,如果给定一个空列表,min
将失败。)
除了@molbdnilo 已经说明的内容之外,对于函数式编程的新手来说,考虑我们在创建循环时实际在做什么可能会有所帮助:我们指定一段代码重复运行。我们需要一个初始状态、一个循环终止条件以及每次迭代之间的更新。
让我们看一下 map 的简单实现。
fun map f [] = []
| map f (x :: xs) = f x :: map f xs
- 列表内容的初始状态。
- 终止条件是列表为空。
- 更新是我们将
f x
添加到将f
映射到列表其余部分的结果的前面。
map 的用处在于我们抽象出了 f
。它可以是任何东西,我们不必担心编写循环样板。
与过程语言中的循环相比,折叠函数更复杂,也更具指导意义。
一个简单的折叠实现。
fun foldl f init [] = init
| foldl f init (x :: xs) = foldl f (f init x) xs
- 我们明确提供了一个初始值和一个要操作的列表。
- 终止条件是列表为空。如果是,我们返回提供的初始值。
- 更新是再次调用该函数。这次更新了初始值,列表是原来的尾部。
考虑对整数列表求和。
foldl op+ 0 [1,2,3,4]
foldl op+ 1 [2,4]
foldl op+ 3 [3,4]
foldl op+ 6 [4]
foldl op+ 10 []
10
折叠很重要,因为很多基本功能都可以用 foldl 或 foldr 来实现。将折叠视为一种将(许多编程语言将这些函数称为“reduce”) 列表简化为某种类型的另一种值的方法。