函数式编程中如何存在时间函数?
我必须承认,我对函数式编程知之甚少。 我从这里到那里读了它,所以知道在函数式编程中,无论调用函数多少次,函数都会返回相同的输出。 它就像数学函数一样,对于涉及函数表达式的输入参数的相同值,计算相同的输出。
例如,考虑这一点:
f(x,y) = x*x + y; //it is a mathematical function
无论你使用f(10,4)
多少次,它的值总是104
。 因此,无论你在哪里写f(10,4)
,都可以用104
替换它,而不必改变整个表达式的值。 该属性被称为表达式的参照透明度。
正如维基百科所说(链接),
相反,在函数代码中,函数的输出值仅依赖于输入到函数的参数,所以用参数x的相同值调用函数f两次将产生两次相同的结果f(x)。
所以我的问题是:函数式编程中是否可以使用时间函数(返回当前时间)?
如果是,那么它如何存在? 它不违反函数式编程的原则吗? 它特别违反了参照透明性,这是函数式编程的一个属性(如果我正确理解它的话)。
或者如果不是,那么在函数式编程中如何知道当前的时间?
解释它的另一种方式是:没有函数可以获取当前时间(因为它不断变化),但是一个动作可以获得当前时间。 假设getClockTime
是一个表示获取当前时间的动作的常量(或者一个无函数函数,如果你喜欢的话)。 无论什么时候使用,这个动作都是一样的,所以它是一个真正的常量。
同样,假设print
是一个需要一些时间表示并将其输出到控制台的函数。 由于函数调用不能在纯功能语言中产生副作用,我们可以想象它是一个函数,它需要一个时间戳并返回将其打印到控制台的操作。 同样,这是一个真正的功能,因为如果您给它一个相同的时间戳,它将每次都返回相同的打印行为。
现在,你怎么能打印当前时间到控制台? 那么,你必须结合这两个行动。 那么我们该怎么做呢? 我们不能只传递getClockTime
来print
,因为print需要一个时间戳,而不是一个动作。 但我们可以想象,有一个操作符>>=
,它将两个操作组合起来,一个获取时间戳,另一个将参数作为参数并打印出来。 将此应用于前面提到的动作,结果是... tadaaa ...获取当前时间并打印它的新动作。 这在Haskell中完全是这样做的。
Prelude> System.Time.getClockTime >>= print
Fri Sep 2 01:13:23 東京 (標準時) 2011
因此,从概念上讲,您可以通过以下方式查看它:纯功能程序不执行任何IO,它定义了一个操作,运行系统随后执行该操作。 每次操作都是相同的,但执行的结果取决于执行时间的情况。
我不知道这是否比其他解释更清楚,但它有时帮助我以这种方式来思考。
是和不是。
不同的FP语言以不同方式解决它
在Haskell(一个非常纯粹的)中,所有这些东西都必须发生在IO Monad这个东西 - 请看这里。 你可以把它看作是获得另一个输入(和输出)到你的函数中(世界状态),或者更容易作为一个“不纯正”像变化的时间发生的地方。
像F#这样的其他语言只是内置了一些不纯,所以你可以有一个函数为同样的输入返回不同的值 - 就像普通的命令式语言一样。
正如Jeffrey Burka在他的评论中提到的那样:这里是直接来自HaskellWiki的IO Monad的介绍。
在Haskell中,人们使用称为monad的构造来处理副作用。 monad基本上意味着你将值封装到一个容器中,并有一些函数将函数从值链接到容器内的值。 如果我们的容器具有以下类型:
data IO a = IO (RealWorld -> (a,RealWorld))
我们可以安全地实施IO操作。 这种类型意味着:类型IO
的动作是一个函数,它接受一个RealWorld
类型的标记并返回一个新的标记以及一个结果。
这背后的想法是每个IO动作都会改变外部状态,由魔法标记RealWorld
。 使用单子,可以链接多个功能,将现实世界变异在一起。 monad最重要的功能是>>=
,发音为bind:
(>>=) :: IO a -> (a -> IO b) -> IO b
>>=
会采取一个动作和一个函数,该函数将采取此动作的结果并从中创建一个新动作。 返回类型是新的操作。 例如,假设现在有一个函数now :: IO String
,它返回表示当前时间的String。 我们可以使用函数putStrLn
将其putStrLn
打印出来:
now >>= putStrLn
或写入do
-Notation,这是势在必行的程序员比较熟悉:
do currTime <- now
putStrLn currTime
所有这些都是纯粹的,因为我们将外部世界的变化和信息映射到RealWorld
令牌。 所以每次你运行这个动作,你当然会得到一个不同的输出,但是输入是不一样的: RealWorld
令牌是不同的。
上一篇: How can a time function exist in functional programming?