函数式编程:副作用实际上在哪里发生? [英] Functional programming : Where does the side effect actually happen?

查看:90
本文介绍了函数式编程:副作用实际上在哪里发生?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

开始学习Haskell之后,即使阅读了大量文档,Haskell还是有些我不理解的地方.

After beginning to learn Haskell, there something I don't understand in Haskell even after reading a lot of documentation.

我了解要执行IO操作,您必须使用将值包装在一种黑匣子"中的"IO monad",因此使用IO monad的任何功能仍然是纯功能.好的,很好,但是IO操作实际上在哪里发生?

I understand that to perform IO operation you have to use a "IO monad" that wrapped a value in a kind of "black box" so the any function that uses the IO monad is still purely functional. OK, fine, but then where does the IO operation actually happen?

这是否意味着Monad本身不是纯粹的功能?还是在IO中实现了IO操作(例如用C语言实现),并将其嵌入"在Haskell编译器中?

Does it mean that a Monad itself is not purely functional? Or is the IO operation implemented, let's say in C, and "embedded" inside the Haskell compiler?

我可以在有或没有Monad的情况下用纯Haskell编写可以进行IO操作的东西吗?如果不是这样,如果在语言本身内部不可能实现,那么该能力从何而来?如果将它嵌入Haskell编译器中/链接到C代码块,IO Monad最终会调用它来执行肮脏的工作"吗?

Can I write, in pure Haskell, with or without a Monad, something that will do an IO operation? And if not, where does this ability come from if it's not possible inside the language itself? If it's embedded/linked inside the Haskell compiler to chunks of C code, will that eventually be called by the IO Monad to do the "dirty job"?

推荐答案

尽管许多引言写得不好,但它不是"IO Monad".只是"IO类型".关于monad并没有什么神奇的. Haskell的Monad类是一件很无聊的事情-它只是陌生的,比大多数语言所支持的更抽象.即使IO实现了Alternative,您也看不到有人将IO称为"IO Alternative".过多地关注Monad只会妨碍学习.

As a preface, it's not "the IO Monad", despite what many poorly-written introductions say. It's just "the IO type". There's nothing magical about monads. Haskell's Monad class is a pretty boring thing - it's just unfamiliar and more abstract than what most languages can support. You don't ever see anyone call IO "the IO Alternative," even though IO implements Alternative. Focusing too much on Monad only gets in the way of learning.

在纯语言中,原则上处理效果(不是副作用!)的概念魔术完全是IO类型的存在.这是真实的类型.不是说这是不纯净的!"的标志.与Maybe[]一样,它是类型为* -> *的完整Haskell类型.接受IO值作为参数的类型签名(例如IO a -> IO (Maybe a))是有意义的.具有嵌套IO的类型签名很有意义,例如IO (IO a).

The conceptual magic for principled handling of effects (not side-effects!) in pure languages is the existence of an IO type at all. It's a real type. It's not some flag saying "This is impure!". It's a full Haskell type of kind * -> *, just like Maybe or []. Type signatures accepting IO values as arguments, like IO a -> IO (Maybe a), make sense. Type signatures with nested IO make sense, like IO (IO a).

因此,如果它是实型,则必须具有具体含义.作为类型的Maybe a表示类型a的可能丢失的值. [a]表示0个或多个a类型的值. IO a表示产生值a类型的一系列效果.

So if it's a real type, it must have a concrete meaning. Maybe a as a type represents a possibly-missing value of type a. [a] means 0 or more values of type a. IO a means a sequence of effects that produce a value of type a.

请注意,IO的全部目的是代表一系列效果.就像我上面说的,它们不是副作用.它们不能被隐藏在程序的无害外观中,并且在其他代码的背后神秘地改变了它们.取而代之的是,效果是IO值,因此可以显式地调用效果.这就是为什么人们尝试使用IO类型来最小化程序部分的原因.您在该处执行的操作越少,远距离进行怪异操作以干扰您的程序的方式就越少.

Note that the entire purpose of IO is to represent a sequence of effects. As I said above, they're not side effects. They can't be hidden away in an innocuous-looking leaf of the program and mysteriously change things behind the back of other code. Instead, effects are rather explicitly called out by the fact that they're an IO value. This is why people attempt to minimize the part of their program using IO types. The less that you do there, the fewer ways there are for spooky action at a distance to interfere with your program.

关于您问题的主旨,那么-一个完整的Haskell程序是一个名为mainIO值,以及它使用的定义的集合.编译器在生成代码时会插入一个确定的非Haskell代码块,该代码块实际上会在IO值中运行效果序列.从某种意义上说,这就是GHC的长期作者之一西蒙·佩顿·琼斯(Simon Peyton Jones)在演讲中谈到的内容 Haskell是没用的.

As to the main thrust of your question, then - a complete Haskell program is an IO value called main, and the collection of definitions it uses. The compiler, when it generates code, inserts a decidedly non-Haskell block of code that actually runs the sequence of effects in an IO value. In some sense, this is what Simon Peyton Jones (one of the long-time authors of GHC) was getting at in his talk Haskell is useless.

的确,实际上执行IO操作的任何东西都不能在概念上保持纯正. (还有一个非常不纯正的函数,它运行在Haskell语言中公开的IO动作.关于支持外来函数接口的添加,我不会说太多,不正确地使用它会严重破坏您的程序. )但是Haskell的重点是为效果系统提供一个原则上的接口,并隐藏不原则的部分.这样做的方式实际上在实践中非常有用.

It's true that whatever actually executes the IO action cannot remain conceptually pure. (And there is that very impure function that runs IO actions exposed within the Haskell language. I won't say more about it than it was added to support the foreign function interface, and using it improperly will break your program very badly.) But the point of Haskell is to provide a principled interface to the effect system, and hide away the unprincipled bits. And it does that in a way that's actually quite useful in practice.

这篇关于函数式编程:副作用实际上在哪里发生?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆