函数式编程中如何存在时间函数?

我必须承认,我对函数式编程知之甚少。 我从这里到那里读了它,所以知道在函数式编程中,无论调用函数多少次,函数都会返回相同的输出。 它就像数学函数一样,对于涉及函数表达式的输入参数的相同值,计算相同的输出。

例如,考虑这一点:

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是一个需要一些时间表示并将其输出到控制台的函数。 由于函数调用不能在纯功能语言中产生副作用,我们可以想象它是一个函数,它需要一个时间戳并返回将其打印到控制台的操作。 同样,这是一个真正的功能,因为如果您给它一个相同的时间戳,它将每次都返回相同的打印行为。

    现在,你怎么能打印当前时间到控制台? 那么,你必须结合这两个行动。 那么我们该怎么做呢? 我们不能只传递getClockTimeprint ,因为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令牌是不同的。

    链接地址: http://www.djcxy.com/p/14141.html

    上一篇: How can a time function exist in functional programming?

    下一篇: Why is this F# sequence function not tail recursive?