函数式语言如何模拟副作用? [英] How do functional languages model side-effects?

查看:24
本文介绍了函数式语言如何模拟副作用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

既然副作用破坏了引用的透明性,难道它们不违背函数式语言的观点吗?

Since side-effects break referential transparency, don't they go against the point of functional languages?

推荐答案

纯函数式编程语言使用两种技术来模拟副作用:

There are two techniques that are used by purely functional programming languages to model side effects:

1) 表示外部状态的世界类型,类型系统保证该类型的每个值仅使用一次.

1) A world type that represents external state, where each value of that type is guaranteed by the type system to be used only once.

在使用这种方法的语言中,函数 printread 可能具有类型 (string, world) ->worldworld ->(string, world) 分别.

In a language that uses this approach the function print and read might have the types (string, world) -> world and world -> (string, world) respectively.

它们可能像这样使用:

let main w =
  let w1 = print ("What's your name?", w) in
  let (name, w2) = read w1 in
  let w3 = print ("Your name is " ^ name, w2) in
  w3

但不是这样:

let main w =
  let w1 = print ("What's your name?", w) in
  let (name, w2) = read w in
  let w3 = print ("Your name is " ^ name, w2) in
  w3

(因为 w 被使用了两次)

(because w is used twice)

所有带有副作用的内置函数都会接受并返回一个世界值.由于所有有副作用的函数要么是内置函数,要么是调用其他有副作用的函数,这意味着所有有副作用的函数都需要获取并返回一个世界.

All built-in functions with side-effects would take and return a world value. Since all functions with side-effects are either built-ins or call other functions with side-effects, this means that all functions with side-effects need to take and return a world.

这样就不可能使用相同的参数两次调用具有副作用的函数,并且不会违反引用透明性.

This way it is not possible to call a function with side-effects twice with the same arguments and referential transparency is not violated.

2) 一个 IO monad,其中所有具有副作用的操作都必须在该 monad 内执行.

2) An IO monad where all operations with side effects have to be executed inside that monad.

使用这种方法,所有具有副作用的操作都将具有 io something 类型.例如 print 将是一个类型为 string ->io unitread 的类型为 io string.

With this approach all operations with side effects would have type io something. For example print would be a function with type string -> io unit and read would have type io string.

访问执行操作的值的唯一方法是使用monadic bind"操作(例如在haskell中称为>>=),将IO操作作为一个参数和一个描述如何处理结果的函数作为另一个操作数.

The only way to access the value of performing operation would be to use the "monadic bind" operation (called >>= in haskell for example) with the IO operation as one argument and a function describing what to do with the result as the other operand.

上面的例子与 monadic IO 看起来像这样:

The example from above would look like this with monadic IO:

let main =
  (print "What's your name?") >>=
  (lambda () -> read >>=
  (lambda name -> print ("Your name is " ^ name)))

这篇关于函数式语言如何模拟副作用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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