功能编程“避免状态和可变数据”。
闭包通过绑定它们的词汇环境来隐藏状态,因此关闭它们的自由变量。
如果它支持闭包,Haskell 如何 purely-functional?他们不打破参考透明度吗?
不,闭包很好并且不会在 Haskell 中引起问题,因为闭包会关闭自由变量的值。您可以隐藏其他语言中的闭包状态的原因是您关闭了引用。如您所知,在 Javascript 中:
var x = 1; var f = function(y) { return y + x; } f(2) // => 3 x = 2; f(2) // => 4
你可以通过在 Haskell 中使用IORef来实际建模:
IORef
main = do x <- newIORef 1 let f y = do x' <- readIORef x return (y + x') r1 <- f 2 writeIORef x 2 r2 <- f 2
这没关系,因为函数f的类型为Int -> IO Int而不是Int -> Int。换句话说,f绑定到相同的操作,但是当执行时,相同的操作可能每次都返回不同的结果。
f
Int -> IO Int
Int -> Int
在 Haskell 中,闭包有自由变量,就像在数学中你可以写f x = x^2一样 - 它不会改变状态。
f x = x^2
我会说 Haskell 避免了可变状态。
闭包不是违规,因为 Haskell 中的所有绑定都是不可变的。什么闭包真正意味着带有自由变量的 lambda 不表示一个独特的函数;它将表示不同的函数,具体取决于每次评估时对其自由变量有效的绑定。 E.g:
makeClosure :: Num a => a -> a -> a makeClosure x = \y -> x+y
表达式makeClosure 5的计算结果与makeClosure 6不同;更重要的是,在程序的不同部分中出现两次makeClosure 5 评估为相同的函数,makeClosure (2+3)或类似函数; i.e。,我们有引用透明度(用等号替换表达式保留了程序的含义)。
makeClosure 5
makeClosure 6
makeClosure (2+3)
在你提到的引用中,你似乎对“州”的含义感到困惑。在这种情况下,国家意味着可变数据;闭包绝对可以“隐藏”数据,但在 Haskell 中,这些数据不可变,因此它不会隐藏状态。与此形成对比的是,根据我的经验,Java 程序员经常说,在有问题的数据不可变的情况下,类实例“隐藏状态”,e.g. ,从构造函数分配给private final实例字段;它们的真正含义是类(和闭包)封装数据。
private final
我的工作人员对“函数式编程”的定义是,如果你将相同的 thing(s)放入,你总是得到相同的 thing(s)。
闭包在 Haskell 中没有违反这个定义(试着想出一个:)的闭包),因此闭包不违反 FP 范式。
4 回答
不,闭包很好并且不会在 Haskell 中引起问题,因为闭包会关闭自由变量的值。您可以隐藏其他语言中的闭包状态的原因是您关闭了引用。如您所知,在 Javascript 中:
你可以通过在 Haskell 中使用
IORef
来实际建模:这没关系,因为函数
f
的类型为Int -> IO Int
而不是Int -> Int
。换句话说,f
绑定到相同的操作,但是当执行时,相同的操作可能每次都返回不同的结果。在 Haskell 中,闭包有自由变量,就像在数学中你可以写
f x = x^2
一样 - 它不会改变状态。我会说 Haskell 避免了可变状态。
闭包不是违规,因为 Haskell 中的所有绑定都是不可变的。什么闭包真正意味着带有自由变量的 lambda 不表示一个独特的函数;它将表示不同的函数,具体取决于每次评估时对其自由变量有效的绑定。 E.g:
表达式
makeClosure 5
的计算结果与makeClosure 6
不同;更重要的是,在程序的不同部分中出现两次makeClosure 5
评估为相同的函数,makeClosure (2+3)
或类似函数; i.e。,我们有引用透明度(用等号替换表达式保留了程序的含义)。在你提到的引用中,你似乎对“州”的含义感到困惑。在这种情况下,国家意味着可变数据;闭包绝对可以“隐藏”数据,但在 Haskell 中,这些数据不可变,因此它不会隐藏状态。与此形成对比的是,根据我的经验,Java 程序员经常说,在有问题的数据不可变的情况下,类实例“隐藏状态”,e.g. ,从构造函数分配给
private final
实例字段;它们的真正含义是类(和闭包)封装数据。我的工作人员对“函数式编程”的定义是,如果你将相同的 thing(s)放入,你总是得到相同的 thing(s)。
闭包在 Haskell 中没有违反这个定义(试着想出一个:)的闭包),因此闭包不违反 FP 范式。