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

本文翻译自:How can a time function exist in functional programming?

I've to admit that I don't know much about functional programming. 我承认我对功能编程知之甚少。 I read about it from here and there, and so came to know that in functional programming, a function returns the same output, for same input, no matter how many times the function is called. 我从这里和那里读到它,因此我们知道在函数式编程中,无论函数被调用多少次,函数都会为相同的输入返回相同的输出。 It's exactly like a mathematical function which evaluates to the same output for the same value of the input parameters which involves in the function expression. 它就像一个数学函数,对于函数表达式中涉及的输入参数的相同值,计算相同的输出。

For example, consider this: 例如,考虑一下:

f(x,y) = x*x + y; // It is a mathematical function

No matter how many times you use f(10,4) , its value will always be 104 . 无论你使用f(10,4)多少次,它的值总是104 As such, wherever you've written f(10,4) , you can replace it with 104 , without altering the value of the whole expression. 因此,无论您何时编写f(10,4) ,都可以将其替换为104 ,而不会更改整个表达式的值。 This property is referred to as referential transparency of an expression. 此属性称为表达式的引用透明度

As Wikipedia says ( link ), 正如维基百科所说( 链接 ),

Conversely, in functional code, the output value of a function depends only on the arguments that are input to the function, so calling a function f twice with the same value for an argument x will produce the same result f(x) both times. 相反,在函数代码中,函数的输出值仅取决于输入到函数的参数,因此使用参数x的相同值调用函数f两次将产生相同的结果f(x)。

Can a time function (which returns the current time) exist in functional programming? 函数式编程中是否存在时间函数(返回当前时间)?

  • If yes, then how can it exist? 如果是,那么它如何存在? Does it not violate the principle of functional programming? 它是否违反了函数式编程的原理? It particularly violates referential transparency which is one of the property of functional programming (if I correctly understand it). 它特别违反了引用透明性 ,这是函数式编程的一个属性(如果我正确理解它)。

  • Or if no, then how can one know the current time in functional programming? 或者如果不是,那么如何才能知道函数式编程中的当前时间?


#1楼

参考:https://stackoom.com/question/UUfw/如何在函数式编程中存在时间函数


#2楼

It can absolutely be done in a purely functional way. 它绝对可以以纯粹的功能方式完成。 There are several ways to do it, but the simplest is to have the time function return not just the time but also the function you must call to get the next time measurement . 有几种方法可以做到这一点,但最简单的方法是让时间函数不仅返回时间,还要返回下次测量时必须调用的函数

In C# you could implement it like this: 在C#中你可以像这样实现它:

// Exposes mutable time as immutable time (poorly, to illustrate by example)
// Although the insides are mutable, the exposed surface is immutable.
public class ClockStamp {
    public static readonly ClockStamp ProgramStartTime = new ClockStamp();
    public readonly DateTime Time;
    private ClockStamp _next;

    private ClockStamp() {
        this.Time = DateTime.Now;
    }
    public ClockStamp NextMeasurement() {
        if (this._next == null) this._next = new ClockStamp();
        return this._next;
    }
}

(Keep in mind that this is an example meant to be simple, not practical. In particular, the list nodes can't be garbage collected because they are rooted by ProgramStartTime.) (请记住,这是一个简单,不实用的示例。特别是,列表节点不能被垃圾收集,因为它们是由ProgramStartTime根源化的。)

This 'ClockStamp' class acts like an immutable linked list, but really the nodes are generated on demand so they can contain the 'current' time. 这个'ClockStamp'类就像一个不可变的链表,但实际上节点是按需生成的,所以它们可以包含'当前'时间。 Any function that wants to measure the time should have a 'clockStamp' parameter and must also return its last time measurement in its result (so the caller doesn't see old measurements), like this: 任何想要测量时间的函数都应该有一个'clockStamp'参数,并且还必须在其结果中返回其最后一次测量(因此调用者看不到旧的测量值),如下所示:

// Immutable. A result accompanied by a clockstamp
public struct TimeStampedValue<T> {
    public readonly ClockStamp Time;
    public readonly T Value;
    public TimeStampedValue(ClockStamp time, T value) {
        this.Time = time;
        this.Value = value;
    }
}

// Times an empty loop.
public static TimeStampedValue<TimeSpan> TimeALoop(ClockStamp lastMeasurement) {
    var start = lastMeasurement.NextMeasurement();
    for (var i = 0; i < 10000000; i++) {
    }
    var end = start.NextMeasurement();
    var duration = end.Time - start.Time;
    return new TimeStampedValue<TimeSpan>(end, duration);
}

public static void Main(String[] args) {
    var clock = ClockStamp.ProgramStartTime;
    var r = TimeALoop(clock);
    var duration = r.Value; //the result
    clock = r.Time; //must now use returned clock, to avoid seeing old measurements
}

Of course, it's a bit inconvenient to have to pass that last measurement in and out, in and out, in and out. 当然,必须将最后一次测量输入和输出,输入和输出,输入和输出都有点不方便。 There are many ways to hide the boilerplate, especially at the language design level. 隐藏样板的方法有很多种,特别是在语言设计层面。 I think Haskell uses this sort of trick and then hides the ugly parts by using monads. 我认为Haskell使用这种技巧,然后使用monad隐藏丑陋的部分。


#3楼

Your question conflates two related measures of a computer language: functional/imperative and pure/impure. 您的问题混淆了计算机语言的两个相关度量:功能/命令和纯/不纯。

A functional language defines relationships between inputs and outputs of functions, and an imperative language describes specific operations in a specific order to perform. 函数式语言定义函数的输入和输出之间的关系,命令式语言以特定的顺序描述特定的操作。

A pure language does not create or depend on side effects, and an impure language uses them throughout. 纯语言不会产生或依赖副作用,而不纯的语言始终使用它们。

One-hundred percent pure programs are basically useless. 百分之百的纯程序基本上没用。 They may perform an interesting calculation, but because they cannot have side effects they have no input or output so you would never know what they calculated. 它们可能会执行一个有趣的计算,但由于它们没有副作用,因此它们没有输入或输出,因此您永远不会知道它们的计算结果。

To be useful at all, a program has to be at least a smidge impure. 为了有用,一个程序必须至少是一个微不足道的。 One way to make a pure program useful is to put it inside a thin impure wrapper. 使纯程序有用的一种方法是将它放在一个薄的不纯包装器中。 Like this untested Haskell program: 像这个未经测试的Haskell程序:

-- this is a pure function, written in functional style.
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)

-- This is an impure wrapper around the pure function, written in imperative style
-- It depends on inputs and produces outputs.
main = do
    putStrLn "Please enter the input parameter"
    inputStr <- readLine
    putStrLn "Starting time:"
    getCurrentTime >>= print
    let inputInt = read inputStr    -- this line is pure
    let result = fib inputInt       -- this is also pure
    putStrLn "Result:"
    print result
    putStrLn "Ending time:"
    getCurrentTime >>= print

#4楼

Yes, it's possible for a pure function to return the time, if it's given that time as a parameter. 是的,如果将该时间作为参数给出,则纯函数可以返回时间。 Different time argument, different time result. 不同的时间参数,不同的时间结果。 Then form other functions of time as well and combine them with a simple vocabulary of function(-of-time)-transforming (higher-order) functions. 然后形成其他时间函数,并将它们与功能(-of-time) - 变换(高阶)函数的简单词汇表组合在一起。 Since the approach is stateless, time here can be continuous (resolution-independent) rather than discrete, greatly boosting modularity . 由于该方法是无状态的,因此这里的时间可以是连续的(与分辨率无关)而不是离散的,从而极大地提高了模块性 This intuition is the basis of Functional Reactive Programming (FRP). 这种直觉是功能反应编程(FRP)的基础。


#5楼

I am surprised that none of the answers or comments mention coalgebras or coinduction. 我很惊讶没有一个答案或评论提到代数或共同引导。 Usually, coinduction is mentioned when reasoning about infinite data structures, but it is also applicable to an endless stream of observations, such as a time register on a CPU. 通常,在推理无限数据结构时会提到共同诱导,但它也适用于无休止的观察流,例如CPU上的时间寄存器。 A coalgebra models hidden state; 代数模型隐藏状态; and coinduction models observing that state. 和coinduction模型观察该状态。 (Normal induction models constructing state.) (正常感应模型构建状态。)

This is a hot topic in Reactive Functional Programming. 这是Reactive Functional Programming的热门话题。 If you're interested in this sort of stuff, read this: http://digitalcommons.ohsu.edu/csetech/91/ (28 pp.) 如果你对这类东西感兴趣,请阅读: http//digitalcommons.ohsu.edu/csetech/91/ (28页)


#6楼

If yes, then how can it exist? 如果是,那么它如何存在? Does it not violate the principle of functional programming? 它是否违反了函数式编程的原理? It particularly violates referential transparency 它特别违反了参考透明度

It does not exist in a purely functional sense. 它不存在于纯粹的功能意义上。

Or if no, then how can one know the current time in functional programming? 或者如果不是,那么如何才能知道函数式编程中的当前时间?

It may first be useful to know how a time is retrieved on a computer. 知道如何在计算机上检索时间可能首先是有用的。 Essentially there is onboard circuitry that keeps track of the time (which is the reason a computer would usually need a small cell battery). 基本上存在跟踪时间的板载电路(这是计算机通常需要小型电池的原因)。 Then there might be some internal process that sets the value of time at a certain memory register. 然后可能会有一些内部进程设置某个内存寄存器的时间值。 Which essentially boils down to a value that can be retrieved by the CPU. 这基本上归结为CPU可以检索的值。


For Haskell, there is a concept of an 'IO action' which represents a type that can be made to carry out some IO process. 对于Haskell,有一个“IO动作”的概念,它表示可以执行某些IO过程的类型。 So instead of referencing a time value we reference a IO Time value. 因此,我们不是引用time值而是引用IO Time值。 All this would be purely functional. 所有这些都是纯粹的功能。 We aren't referencing time but something along the lines of 'read the value of the time register' . 我们没有引用time而是“读取时间寄存器的值”

When we actually execute the Haskell program, the IO action would actually take place. 当我们实际执行Haskell程序时,实际上会发生IO操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值