Questions tagged «monad»


5
批评IO monad被视为在世界上运作的州monad
IOHaskell中的单子通常被解释为州是世界的州单子。因此,将IO amonad 类型的值视为worldState -> (a, worldState)。 前一段时间,我读了一篇文章(或博客/邮件列表帖子),该文章批评了这种观点,并提出了一些不正确的原因。但是我既不记得这篇文章,也不记得原因。有人知道吗 编辑:这篇文章似乎丢失了,所以让我们在这里开始收集各种参数。 我开始悬赏以使事情变得更有趣。 编辑:该文章中,我一直在寻找的应对尴尬的阵容:单子输入/输出,并发性,异常和外国语言的Haskell中调用由西蒙·佩顿-琼斯。(感谢TacTics的回答。)


3
查看单子的不同方法
在学习Haskell的过程中,我遇到了很多教程,试图解释什么是monad,以及为什么monad在Haskell中很重要。他们每个人都使用类比,因此更容易理解其含义。归根结底,我对单子是3种不同的看法: 查看1:将Monad作为标签 有时我认为将monad作为特定类型的标签。例如,一个类型的函数: myfunction :: IO Int myfunction是一个函数,无论何时执行它都会产生一个Int值。结果的类型不是Int,而是IO Int。因此,IO是Int值的标签,警告用户知道Int值是执行IO操作的过程的结果。 因此,此Int值已被标记为来自具有IO的过程的值,因此该值为“脏”。您的过程不再是纯粹的。 视图2:莫纳德(Monad)是可能发生令人讨厌的事情的私人空间。 在所有过程都是纯且严格的系统中,有时您需要产生副作用。因此,monad只是一个很小的空间,允许您做讨厌的副作用。在这个空间中,您可以逃脱纯净的世界,走不纯净的事物,进行过程,然后返回有价值的东西。 图3:Monad的范畴论 我不完全理解这种观点。monad只是同一类别或子类别的函子。例如,您具有Int值,并且作为IO Int子类,它们是在IO过程之后生成的Int值。 这些观点正确吗?哪个更准确?

2
Monad是继承层次结构的可行替代方法吗?
我将使用像monads这样的语言不可知的描述,首先描述monoid: 甲独异是(大约)的一组需要一些类型作为参数并返回相同的类型的功能。 甲单子是(大约)的一组需要的功能封装器类型作为参数并返回相同的包装类型。 注意这些是描述,而不是定义。随意攻击该描述! 因此,在OO语言中,monad允许以下操作组合: Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land() 请注意,monad定义并控制这些操作的语义,而不是所包含的类。 传统上,在OO语言中,我们将使用类层次结构和继承来提供这些语义。因此,我们将有一个Bird带有方法takeOff(),flyAround()和的类land(),而Duck将继承这些方法。 但是后来我们遇到了不能飞的鸟,因为penguin.takeOff()失败了。我们必须求助于异常抛出和处理。 另外,一旦我们说企鹅是a Bird,我们就会遇到多重继承问题,例如,如果我们也有的层次结构Swimmer。 本质上,我们试图将类归类(对“分类论”的人道歉),并按类别而不是单个类来定义语义。但是,与层次结构相比,monad似乎是一种更清晰的机制。 因此,在这种情况下,我们将有一个Flier<T>单子,如上面的示例: Flier<Duck> m = new Flier<Duck>(duck).takeOff().flyAround().land() ...而且我们永远不会实例化一个Flier<Penguin>。我们甚至可以使用静态类型来防止这种情况的发生,也许使用标记接口。或运行时功能检查以纾困。但是,实际上,程序员切勿将企鹅放入Flier,从同样的意义上讲,它们切勿除以零。 而且,它更普遍适用。飞行器不必一定是鸟。例如Flier<Pterodactyl>或Flier<Squirrel>,而不更改这些单个类型的语义。 一旦我们通过容器上的可组合函数对语义进行了分类(而不是按类型层次结构进行分类),它就解决了“某种行为,某种行为不适合”特定类的旧问题。它还轻松明确地为一个类提供了多种语义,例如Flier<Duck>和Swimmer<Duck>。似乎我们一直在通过按类层次结构对行为进行分类来应对阻抗不匹配的问题。Monad优雅地处理它。 因此,我的问题是,就像我们倾向于偏爱组成而非继承一样,偏爱单子而不是继承是否也有意义? (顺便说一句,我不确定是应该在这里还是在Comp Sci中使用,但这似乎更像是一个实际的建模问题。但是也许在那儿会更好。)

4
IO monad模式处理副作用的好处是否纯粹是学术上的?
对不起,还有另一个FP +副作用问题,但是我找不到一个可以完全回答我的问题。 我对函数式编程的(有限的)理解是,应将状态/副作用最小化并与无状态逻辑分开。 我还收集了Haskell的方法,即IO monad,它通过将有状态的动作包装在一个容器中以供以后执行(被认为超出程序本身的范围)来实现。 我试图理解这种模式,但实际上是确定是否在Python项目中使用它,因此要避免使用Haskell规范。 粗暴的例子来了。 如果我的程序将XML文件转换为JSON文件: def main(): xml_data = read_file('input.xml') # impure json_data = convert(xml_data) # pure write_file('output.json', json_data) # impure IO monad的方法不是有效地做到这一点: steps = list( read_file, convert, write_file, ) 然后通过不实际调用这些步骤来放任自己的责任,而是让口译员这样做? 换一种说法,就像写: def main(): # pure def inner(): # impure xml_data = read_file('input.xml') json_data = convert(xml_data) write_file('output.json', …

2
什么是Comonad,它们有什么用?
最近,我一直在整理关于Monads工作原理的知识。还向我介绍了'Comonad'的概念,它被描述为monad 的逆对偶。但是,我不可能把头缠住它。 为了了解Monad,我为自己做了一个比喻: Monads可以看作是“构建表达传送带的蓝图”。 要定义一个新的Monad(一种新型的传送带系统),您需要定义: 一种在传送带上放置东西的方法,例如“启动”传送带。(称为unit或return) 将作为传送带一部分的机器(表达式)连接到传送带的一种方式。(称为join或bind或>>=)。 (第三项操作是将当前的传送带取走,将其内含物扔掉,然后启动一个新的传送带,称为>>,但很少使用。) 为了使机器和输送机正常工作,您需要确保: 如果将某些东西放在传送带上并使其通过机器,则输出应与手动将其通过机器时的输出相同。(左身份) 如果要将传送带放在已经存在的传送带之间,则不应以顶部带有传送带的传送带结尾,而应使用一条更长的传送带。 (正确身份) 如果您手动使用机器A,然后将结果传递到连接传送带的BC,或者如果您使用机器,将结果传递给连接的AB,然后手动将结果传递给C,则对于输出无所谓。 >> = b)>> = c)应该与(a >> =(b >> = c))相同(关联性) 最简单的传送带就是那种只接受输入并始终继续到下一个表达式的传送带。这就是“管道”。 另一种可能性是,只有在满足该条件的条件下,才让它通过下一台机器。这意味着,如果在它们之间的某些表达式中,该值更改为不再允许的值,则将跳过其余的表达式。这就是“也许”单子在Haskell中所做的事情。 您还可以在将值传递到计算机之前或之后对值执行其他特殊的条件性复制/更改规则。一个示例:解析器(此处,如果表达式返回“失败”结果,则将表达式之前的值 用作输出)。 当然,这个比喻不是完美的,但我希望它能很好地说明单子的工作原理。 但是,我很难理解这种类比,以理解Comonads。我从互联网上发现的少量信息中得知Comonad定义了以下信息: extract,这与的相反return,也就是说,它从 Comonad中取出一个值。 duplicate,这与的倒数相同join,也就是说,它从一个中创建了两个Comonad。 但是,如果我们只能从它们中提取或复制它们,该如何实例化Comonad?以及如何实际使用它们?我已经看到了这个非常了不起的项目以及有关它的讨论(很遗憾,我对此了解很少),但是我不确定Comonad到底提供了部分功能。 什么是Comonad?它们有什么用?如何使用它们?它们可食用吗?

1
Free monad和Reactive Extensions如何关联?
我来自C#背景,其中LINQ演变为Rx.NET,但始终对FP感兴趣。在对Monad和F#中的一些辅助项目进行了一些介绍之后,我准备尝试进入下一个级别。 现在,经过来自Scala的人们关于免费monad的几次讨论,以及在Haskell或F#中的多次写作之后,我发现带有用于理解的口译员的语法与IObservable锁链非常相似。 在FRP中,您将根据较小的领域特定块(包括链中的副作用和失败)组成操作定义,并将应用程序建模为一组操作和副作用。在免费monad中,如果我理解正确,您可以通过将操作设为函子,然后使用coyoneda来进行操作。 将针头朝任何一种方法倾斜的两者之间有什么区别?定义服务或程序时的根本区别是什么?

4
Monads解决什么编程问题?[关闭]
已关闭。这个问题需要更加集中。它当前不接受答案。 想改善这个问题吗?更新问题,使其仅通过编辑此帖子来关注一个问题。 3年前关闭。 我读过很多文章来解释什么是单子,如何使用unit和bind工作,其中一些直接陷入类别理论,如此抽象(至少对我而言),使眼睛流血,有些人完全忽略了这些,并触及了奇怪的类比。墨西哥卷饼,盒子和什么不。 经过几周的研究和大量的油炸神经元,(我认为)我了解了Monads的工作原理。但是,还有一件事让我无法理解,实际上很少有文章涉及(IO和状态除外): 为什么? 为什么Monad重要?他们为什么如此重要?他们正在解决什么问题?那些问题只能用Monad来解决吗,或者还有其他方法吗?

2
为什么不像Haskell那样将Scala Option类型称为Maybe?[关闭]
已关闭。这个问题是基于观点的。它当前不接受答案。 想改善这个问题吗?更新问题,以便通过编辑此帖子以事实和引用的形式回答。 4年前关闭。 为什么不像Haskell那样将Scala Option类型称为Maybe? 也许对我来说更具“语义意义”,但也许Option具有我所不知道的不同行为。 有什么特殊的原因为什么不将Scala中的Option称为Maybe?

4
在以“功能”风格进行编程时,您是否在应用程序逻辑中编织了一个应用程序状态?
如何构建具有以下所有功能的系统: 对不可变对象使用纯函数。 只传递给它所需功能的数据,不再传递(即没有大的应用程序状态对象) 避免对函数使用过多的参数。 避免仅出于将参数打包和拆包到函数的目的而构造新对象的方法,只是避免将过多的参数传递给函数。如果我要将多个项目作为一个对象打包到一个函数中,则我希望该对象成为该数据的所有者,而不是临时构造的东西 在我看来,State monad违反了规则2,虽然它并不明显,因为它是通过monad编织而成的。 我觉得我需要以某种方式使用Lenses,但是关于非功能语言的文章很少。 背景 作为练习,我将现有的应用程序之一从面向对象的样式转换为功能样式。我要尝试做的第一件事是尽可能多地利用应用程序的内核。 我听到的一件事是,如何用一种纯函数式的语言来管理“状态”,而我相信这是由State monad完成的,从逻辑上讲,您称一个纯函数为“传递状态”。世界原样”,那么当函数返回时,它会返回给您变化后的世界状态。 为了说明这一点,您可以用一种纯粹的功能性方式来创建“ hello world”的方式有点像,您将程序的屏幕状态传递给程序,然后返回印有“ hello world”状态的屏幕状态。因此,从技术上讲,您要调用一个纯函数,并且没有副作用。 基于此,我遍历了我的应用程序,并且:1.首先将我的所有应用程序状态放入单个全局对象(GameState)中。2.其次,使GameState不可变。您无法更改。如果需要更改,则必须构造一个新的。我通过添加一个复制构造函数来做到这一点,该复制构造函数可以选择接受一个或多个已更改的字段。3.对于每个应用程序,我都将GameState作为参数传递。在函数内,在完成将要执行的操作后,它将创建一个新的GameState并返回它。 我如何拥有纯功能核心,以及外部的循环,该循环将GameState馈入应用程序的主工作流程循环。 我的问题: 现在,我的问题是,GameState有大约15个不同的不可变对象。最低级别的许多功能仅对其中一些对象起作用,例如保持得分。因此,假设我有一个计算得分的函数。今天,GameState传递给此函数,该函数通过使用新分数创建新的GameState来修改分数。 似乎有些错误。该功能不需要完整的GameState。它只需要Score对象。所以我更新了它以传递分数,并仅返回分数。 这似乎很有意义,所以我进一步介绍了其他功能。有些功能需要我从GameState传入2、3或4个参数,但是随着我一直在应用程序的外部核心中使用该模式,我传入了越来越多的应用程序状态。就像在工作流循环的顶部,我将调用一个方法,该方法将调用将调用一个方法的方法,依此类推,一直到计算分数为止。这意味着当前分数会通过所有这些层,只是因为最底层的函数将要计算分数。 所以现在我有了带有数十个参数的函数。我可以将这些参数放入一个对象中以减少参数数量,但是然后我希望该类成为状态应用程序状态的主位置,而不是在调用时简单地构造以避免重复传递的对象输入多个参数,然后解压缩它们。 所以现在我想知道我的问题是否是我的函数嵌套得太深了。这是因为希望具有较小的功能,所以我在一个功能变大时进行重构,然后将其拆分为多个较小的功能。但是这样做会产生更深的层次结构,即使外部函数未直接在这些对象上运行,传递给内部函数的所有内容也都必须传递给外部函数。 似乎只是在避免这种问题的过程中传入了GameState。但是我回到了原来的问题,即向函数传递比函数所需更多的信息。

1
期货/单股vs事件
在可以忽略性能影响(最大每秒10-20个事件)的应用程序框架中, 什么是更可维护且更灵活的方法,可以用作模块之间进行通信的首选介质-事件还是期货/承诺/单子? 人们常说,事件(发布/订阅,中介)允许松散耦合,因此-应用程序更易于维护...我的经验否认这一点:一旦您拥有20多个事件,调试就会变得很困难,重构也会变得更加困难-因为很难看到:谁,何时何地使用什么。 承诺(我用Java语言编写)比事件要丑陋得多。但是:您可以清楚地看到函数调用之间的连接,因此应用程序逻辑变得更加简单明了。我怕什么 但是,Promises会带来更多的困难吗? ps:答案不一定基于JS,非常欢迎其他功能语言的经验。

1
最好在monadic函数中使用带验证的错误monad,还是直接在绑定中实现带有验证的自己的monad?
我想知道对于可用性/可维护性而言,更好的设计明智之举,以及与社区相适应的更好之道。 给定数据模型: type Name = String data Amount = Out | Some | Enough | Plenty deriving (Show, Eq) data Container = Container Name deriving (Show, Eq) data Category = Category Name deriving (Show, Eq) data Store = Store Name [Category] deriving (Show, Eq) data Item = Item Name Container …

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.