什么是monoid的实际用途?

马克·卡波夫

我正在阅读“了解Haskell的知识”,并且已经学习了应用程序知识,现在使用的是类半身像。尽管我发现应用程序在实践中很有用,而monoid却并非如此,但我对两者的理解都没有问题。所以我想我对Haskell不了解。

首先,谈到Applicative,它会创建类似统一语法的内容,以对“容器”执行各种操作。因此,我们可以使用普通函数对Maybe列表执行操作IO(我应该说单子吗?我还不知道单子),函数:

λ> :m + Control.Applicative
λ> (+) <$> (Just 10) <*> (Just 13)
Just 23
λ> (+) <$> [1..5] <*> [1..5]
[2,3,4,5,6,3,4,5,6,7,4,5,6,7,8,5,6,7,8,9,6,7,8,9,10]
λ> (++) <$> getLine <*> getLine
one line
 and another one
"one line and another one"
λ> (+) <$> (* 7) <*> (+ 7) $ 10
87

因此,应用性是一种抽象。我认为我们可以没有它,但是它可以帮助清晰地表达一些想法,这很好。

现在,让我们来看看Monoid它也是抽象且非常简单的一种。但这对我们有帮助吗?对于这本书中的每个示例,很明显,有更清晰的方法可以用来做这些事情:

λ> :m + Data.Monoid
λ> mempty :: [a]
[]
λ> [1..3] `mappend` [4..6]
[1,2,3,4,5,6]
λ> [1..3] ++ [4..6]
[1,2,3,4,5,6]
λ> mconcat [[1,2],[3,6],[9]]
[1,2,3,6,9]
λ> concat [[1,2],[3,6],[9]]
[1,2,3,6,9]
λ> getProduct $ Product 3 `mappend` Product 9
27
λ> 3 * 9
27
λ> getProduct $ Product 3 `mappend` Product 4 `mappend` Product 2
24
λ> product [3,4,2]
24
λ> getSum . mconcat . map Sum $ [1,2,3]
6
λ> sum [1..3]
6
λ> getAny . mconcat . map Any $ [False, False, False, True]
True
λ> or [False, False, False, True]
True
λ> getAll . mconcat . map All $ [True, True, True]
True
λ> and [True, True, True]
True

因此,我们注意到了一些模式并创建了新的类型类...很好,我喜欢数学。但是从实用的角度来看,有什么意义Monoid呢?它如何帮助我们更好地表达想法?

大师级

加布里埃尔·冈萨雷斯(Gabriel Gonzalez)在他的博客中写了关于为什么应该和应该真正关心的重要信息。您可以在这里阅读(也可以查看此内容)。

这与API的可伸缩性,体系结构和设计有关。这个想法是,有一个“常规架构”说:

将几种类型的A组合在一起以生成类型B的“网络”或“拓扑”

这种设计的问题在于,随着程序的扩展,重构时地狱也随之而来。

因此,您想更改模块A来改进您的设计或领域,所以您可以这样做。哦,但是现在依赖于A的模块B&C坏了。您修复了B,太好了。现在,您修复了C。现在B又一次崩溃了,因为B也使用了C的某些功能。我可以永远这样做,如果您曾经使用过OOP,也可以。

然后就是加百列所说的“ Haskell体系结构”:

将几种类型A的组分组合在一起,以生成相同类型A的新组分,其特性与其取代基部分没有区别

这也很好地解决了这个问题。基本上:不要将模块分层或扩展为专用模块。
相反,结合起来。

因此,现在鼓励您的是,不要说“我有多个X,因此让我们创建一个类型来表示它们的并集”,而是说“我有多个X,因此将它们组合成一个X”。或用简单的英语:“首先让我们创建可组合类型”。(您感觉到类人猿潜伏了吗?)。

假设您想为您的网页或应用程序创建一个表单,并且由于需要个人信息而创建了模块“个人信息表单”。后来,您发现您还需要“更改图片表格”,因此很快就写下了。现在您说我想将它们结合起来,所以让我们制作一个“个人信息和图片表格”模块。在现实生活中,可扩展的应用程序可以而且确实会失控。可能不是用表格而是为了演示,您需要撰写和撰写文章,因此最终您将获得“个人信息&更改图片&更改密码&更改状态&管理朋友&管理心愿单&更改视图设置&请不要再扩展我了&Please&please stop!&STOP !!!!“ 模块。这不漂亮 并且您将不得不在API中管理这种复杂性。哦,如果您要更改任何内容,则可能有依赖性。所以..是的..欢迎来到地狱。

现在让我们看一下其他选择,但是首先让我们看一下好处,因为它会指导我们实现这一目标:

这些抽象无限扩展,因为它们始终保持可组合性,因此我们永远不需要在顶部放置更多抽象。这就是您应该学习Haskell的原因之一:您将学习如何构建平面架构。

听起来不错,所以不要停下来思考“我们是否可以将此处的内容组合起来”,而不是制作“个人信息表格” /“更改图片表格”模块。好吧,我们可以制作一个“表格”,对吗?也会更加抽象。
然后,有可能为您想要的所有内容构建一个表单,将它们组合在一起并获得与其他表单一样的表单。

因此,您不再需要凌乱的复杂树,因为采用两种形式并获得一种形式的关键。这样Form -> Form -> Form正如您已经清楚看到的那样,此签名是的实例mappend

另一种选择,和传统的架构可能会看起来像a -> b -> c,然后c -> d -> e,然后......

现在,有了表格,它并不是那么具有挑战性。挑战是在现实世界的应用程序中使用它。为此,您只需要尽可能多地问自己(因为如您所见,它会有所回报):我如何使这个概念可组合?并且由于Monoid是实现这一目标的简单方法(我们希望简单),首先请问自己:这个概念如何成为Monoid?

旁注:幸运的是,Haskell将非常不鼓励您扩展类型,因为它是一种功能语言(无继承)。但是仍然有可能为某种事物创建一个类型,为某种事物创建另一个类型,并且在第三种类型中将这两种类型都作为字段。如果这是为了合成-请查看是否可以避免。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章