如果纯粹是功能强大的,为什么可以在Haskell中休眠/暂停执行? [英] Why is it possible to sleep / pause execution in Haskell if it's purely functional?

查看:63
本文介绍了如果纯粹是功能强大的,为什么可以在Haskell中休眠/暂停执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到Haskell具有称为延迟"的睡眠功能: Control.Concurrent.Thread.Delay

I saw Haskell has a sleep function called "delay": Control.Concurrent.Thread.Delay

我的问题是:如果Haskell是功能的,那么怎么会有这样的事情?难道不是在睡觉吗?或者我想念东西吗?

My question is: if Haskell is purely functional, how is it possible to have such thing like this? Isn't sleep a collateral effect or am I missing something?

推荐答案

好的,将我的评论移至答案.请注意,IO monad和这些想法有多个视图.您可以通过唯一性类型和类似的方式获得类似的结果.

Alright, moving my comment to an answer. Do note that there are multiple views of the IO monad and these ideas. You can achieve similar results with uniqueness types and whatnot.

我只是发现这是最简单,最酷的解释.

I just happen to find this the simplest and coolest explanation.

Haskell是一种纯粹的功能语言.这意味着评估Haskell程序应始终产生相同的结果.但是,情况似乎并非如此!看类似的东西

Haskell is a purely functional language. This should mean that evaluating a Haskell program should always produce the same results. However, that doesn't seem like the case! Look at something like

-- Echo.hs
main :: IO ()
main = getLine >>= putStrLn

这似乎有所不同,具体取决于用户的输入.

This seems to do something different depending on user input.

实际上,生活在IO中的任何东西看起来都可以做很多不同的事情,这取决于从月球状态到薛定inger猫的人寿保险费用.

Really anything that lives in IO looks like it can do wildly different things depending on everything from the state of the moon to the life insurance costs of Schrodinger's cat.

此外,看来可以做任何有用事情的任何语言都是不纯净的.除非您有兴趣观看CPU旋转,否则产生副作用就是程序存在的全部原因!

More over, it seems like any language that can do anything useful must be impure. Unless your interested in watching your CPU spin, producing side effects is all that programs exist for after all!

实际上并非如此!适当的心理模型是将IO想象为

In fact this isn't actually the case! The appropriate mental model is to imagine IO as something like

data IO a = PutStrLn String a
          | GetLine (String -> a)
          ...

因此,IO可能只是一种数据结构,代表一种程序执行的计划".然后邪恶的,不纯洁的Haskell运行时实际上执行了该计划,并产生了您看到的结果.

So IO could just be a data structure representing a sort of "plan" for the program to execute. Then the evil impure Haskell runtime actually executes this plan, producing the results you see.

这不仅是一个小小的语义问题,我们可以做类似的事情

This isn't just a minor semantic quibble though, we can do something like

runBackwards :: [IO ()] -> IO ()
runBackwards  = foldr (>>) (return ()) . reverse

换句话说,我们可以将我们的计划"作为正常的一等值使用.

In other words we can manipulate our "plans" as normal, first class values.

我们可以评估它们,用力压迫它们,在它们上掉很多吨,甚至在背后说些卑鄙的话,它们永远不会产生副作用!他们看不到,普通的Haskell代码只能建立IO操作以在运行时进行评估,无法执行任何明显的操作.

We can evaluate them, force them, drop a ton of bricks on them, even say mean things about them behind their backs and they'll never produce a side effect! They can't you see, normal Haskell code can only build up IO actions to be evaluated by the run time, it's incapable of doing anything noticeable.

在某种程度上,您几乎可以将Haskell程序视为元编程的最终形式,可以在运行时即时生成程序,并由某些解释程序对其进行评估.

In a way you can almost view a Haskell program as the ultimate form of metaprogramming, producing programs on the fly during runtime and having them evaluated by some interpreter.

所以当你说

 foo = delay 20

您并不是说将这个程序延迟20个时间",而是说在此代码构建的程序中,在其运行时将其执行暂停20个时间".

You're not saying "Delay this program for 20 whatevers", you're saying "In the program that this code builds, pause its execution for 20 whatevers when it runs".

问谁在乎"是很公平的:该代码是否在某个时候运行,谁在乎谁运行它?以这种方式纯粹发挥功能有什么好处?它实际上可以产生一些有趣的效果(呵呵).

It's fair to ask "Who Cares": if this code gets run at some point who cares who runs it? What good does it do to be purely functional in this way? It can actually have some interesting effects (heh).

例如,考虑类似 http://www.tryhaskell.org 之类的东西,显然它需要运行Haskell代码,但是也不能盲目执行它得到的任何IO!它可以做的是提供IO的不同实现,同时公开相同的API.

For example, think of something like http://www.tryhaskell.org, clearly it needs to run Haskell code, but it also can't just blindly execute whatever IO it gets! What it can do is provide a different implementation of IO, while exposing an identical API.

这个新的IO可以建立一个像数据结构这样的漂亮树,可以很容易地对其进行清理并由Web后端进行检查,以确保它从不运行任何恶意.我们甚至可以将伪造的IO结构编译为GHC提供的常规结构,并在服务器上有效地执行它!由于从一开始就没有任何邪恶,我们只需要相信我们编写的代码即可.

This new IO builds up a nice tree like datastructure which can be easily sanitized and checked by the web backend to ensure that it never runs something evil. We can even compile our fake-IO structure to the normal one that GHC provides and execute it efficiently on the server! Since there's never anything evil in their to begin with we only have to trust code we wrote.

没有更多无尽的applet风格的安全漏洞.通过替换IO,我们毫无疑问地知道我们可以执行此代码,并且绝不会尝试做任何恶作剧.

No more endless applet-style security holes. By replacing IO we know beyond a shadow of a doubt that we can execute this code and it will never attempt to do something evil.

实际上,这种建立数据结构的概念不仅对IO有用.这是构造任何旨在提供有限DSL的项目的好方法.来自

In fact, this notion of building up data structures is useful for more than just IO. It's a great way to structure any project that aims to provide a limited DSL. Anything from

  • 一种查询语言
  • 游戏脚本
  • 代码生成
  • 写客户端haskell"

所有这些都可以通过建立常规数据结构并将其编译"为适当的语言来解决.通常的技巧是使用免费monad .如果您是中级Haskeller,请去学习em!

All of these can be solved by building up normal datastructures and "compiling" them to the appropriate language. The usual trick for this is to use a free monad. If you're an intermediate Haskeller, go learn about em!

这篇关于如果纯粹是功能强大的,为什么可以在Haskell中休眠/暂停执行?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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