函数式编程:何时使用哪种抽象
Functional programming: When to use which abstraction
函数式编程中有很多模式。例如Monoids、Monads、Functors e.t.c 但这些都是非常高级的抽象,人们真的不知道什么时候使用哪个。
例如当您想将 A 的几项减少为 A
的一项时,幺半群很有用
从这个意义上说,这些抽象试图解决什么问题?
也许我们可以展示程序员在 monoid
被发现之前如何处理问题,以及他们如何使用 monoid
处理相同的问题
那些模式是数学概念,它们要么适用于您的程序,要么不适用于您的程序。你可以在没有它们的情况下编写完全相同的代码,你只会开始注意到你的许多针对不同数据类型的函数共享一个共同的结构。
不仅每种数据类型都需要不同的函数来处理这种常见的事情,而且所有的辅助函数都需要为每种数据类型重写。这是您发现要使用抽象的时候。您检查哪个类型类与通用结构匹配并提供预期的辅助函数,然后将其应用于您的数据类型。
关于您的具体示例:在 Monoid
s 之前是 "discovered",每个人都使用 ++
附加两个列表,并使用 concat
附加多个列表。同样,他们使用 +
对两个数字求和,并使用 sum
对多个数字求和。如果有人写了一棵树,其元素应该折叠成单个值,他必须使用相应的操作为列表编写一个实现,为数字编写一个实现。
现在,有了幺半群,我们可以抽象具体类型,并为任意幺半群编写树实现。我们使用 mappend
和 mconcat
操作而不是特定的操作,并且我们的树适用于列表和数字。甚至任何其他幺半群。
函数式编程中有很多模式。例如Monoids、Monads、Functors e.t.c 但这些都是非常高级的抽象,人们真的不知道什么时候使用哪个。
例如当您想将 A 的几项减少为 A
的一项时,幺半群很有用从这个意义上说,这些抽象试图解决什么问题?
也许我们可以展示程序员在 monoid
被发现之前如何处理问题,以及他们如何使用 monoid
那些模式是数学概念,它们要么适用于您的程序,要么不适用于您的程序。你可以在没有它们的情况下编写完全相同的代码,你只会开始注意到你的许多针对不同数据类型的函数共享一个共同的结构。
不仅每种数据类型都需要不同的函数来处理这种常见的事情,而且所有的辅助函数都需要为每种数据类型重写。这是您发现要使用抽象的时候。您检查哪个类型类与通用结构匹配并提供预期的辅助函数,然后将其应用于您的数据类型。
关于您的具体示例:在 Monoid
s 之前是 "discovered",每个人都使用 ++
附加两个列表,并使用 concat
附加多个列表。同样,他们使用 +
对两个数字求和,并使用 sum
对多个数字求和。如果有人写了一棵树,其元素应该折叠成单个值,他必须使用相应的操作为列表编写一个实现,为数字编写一个实现。
现在,有了幺半群,我们可以抽象具体类型,并为任意幺半群编写树实现。我们使用 mappend
和 mconcat
操作而不是特定的操作,并且我们的树适用于列表和数字。甚至任何其他幺半群。