功能语言如何建模副作用? [英] How do functional languages model side-effects?

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

问题描述

由于副作用会破坏引用透明性,请不要违背函数式语言的要点? 有解决方案

有两种技术被纯函数式编程语言用于建模副作用:1)一种表示外部状态的世界类型,其中每种类型的值都由类型系统只能使用一次。



在使用这种方法的语言中,函数 print read 可能有类型(string,world) - >世界世界 - > (字符串,世界)



它们可能是这样使用的:

<$在$ b $中让(str,w2)=读取w1中的$ w $ = print(你叫什么名字?,w) b在
w3



但不是这样:

  let main w = 
let w1 = print(你叫什么名字? w)in
let(str,w2)=读取
中的w w3 = print(Your name is^ name,w2)in
w3


$ b

(因为w被使用了两次)

所有内置函数 - 影响会带来并回报世界价值。因为所有带副作用的函数都是内置函数或者带有副作用的其他函数,这意味着所有带副作用的函数都需要接受并返回一个世界。



这种方式不可能用相同的参数两次调用带副作用的函数,并且不违反引用透明。


2)一个IO单元,其中所有带副作用的操作都必须在monad中执行。



使用这种方法,所有带副作用的操作都应该有 i 。例如 print 应该是一个类型为 string - >的函数。 io unit read 应该有类型 io string



访问执行操作的值的唯一方法是使用monadic bind操作(例如,在haskell中称为>> =)将IO操作作为一个参数并描述一个函数



上面的例子看起来像是一元IO:

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


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) A world type that represents external state, where each value of that type is guaranteed by the type system to be used only once.

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

They might be used like this:

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

But not like this:

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

(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) An IO monad where all operations with side effects have to be executed inside that monad.

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.

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.

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天全站免登陆