[scala] ¿Cómo puede existir una función de tiempo en la programación funcional?



Answers

Si y no.

Los diferentes lenguajes de FP los resuelven de manera diferente.

En Haskell (una muy pura) todo esto tiene que suceder en algo llamado IO Monad : mira here . Puedes pensar que se trata de obtener otra entrada (y salida) en tu función (el estado-mundo) o más fácil como un lugar donde ocurre "impureza" como obtener el cambio de hora.

Otros lenguajes como F # solo tienen un poco de impureza incorporada, por lo que puede tener una función que devuelva diferentes valores para la misma entrada, al igual que los lenguajes imperativos normales .

Como Jeffrey Burka mencionó en su comentario: Aquí está la buena intro a la IO Monad directamente desde HaskellWiki.

Question

Debo admitir que no sé mucho sobre programación funcional. Leí sobre esto de aquí para allá, y así llegué a saber que en la programación funcional, una función devuelve el mismo resultado, para la misma entrada, sin importar cuántas veces se llame a la función. Es exactamente como la función matemática que evalúa a la misma salida para el mismo valor de parámetro de entrada que implica en la expresión de la función.

Por ejemplo, considera esto:

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

No importa cuántas veces use f(10,4) , su valor siempre será 104 . Como tal, donde sea que hayas escrito f(10,4) , puedes reemplazarlo por 104 , sin alterar el valor de la expresión completa. Esta propiedad se conoce como transparencia referencial de una expresión.

Como dice Wikipedia ( link ),

Por el contrario, en el código funcional, el valor de salida de una función depende solo de los argumentos que ingresan a la función, por lo que llamar a una función f dos veces con el mismo valor para un argumento x producirá el mismo resultado f (x) ambas veces.

Entonces mi pregunta es: ¿puede una función de tiempo (que devuelve la hora actual ) existir en la programación funcional?

  • Si es así, ¿cómo puede existir? ¿No viola el principio de la programación funcional? Viola particularmente la transparencia referencial, que es una de las propiedades de la programación funcional (si la entiendo correctamente).

  • O si no, ¿cómo se puede saber la hora actual en la programación funcional?




Sí, es posible que una función pura devuelva el tiempo, si se le da ese tiempo como parámetro. Diferente argumento de tiempo, diferente resultado de tiempo. A continuación, forme también otras funciones del tiempo y combínelas con un vocabulario simple de funciones (-of-time) -transformando (funciones de orden superior). Como el enfoque es sin estado, el tiempo aquí puede ser continuo (independiente de la resolución) en lugar de discreto, lo que aumenta en gran medida la modularidad . Esta intuición es la base de la Programación Reactiva Funcional (FRP).




Se puede hacer absolutamente de una manera puramente funcional. Hay varias maneras de hacerlo, pero la más simple es hacer que la función de tiempo devuelva no solo el tiempo sino también la función a la que debe llamar para obtener la próxima medición de tiempo .

En C # podrías implementarlo así:

// 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;
    }
}

(Tenga en cuenta que este es un ejemplo que pretende ser simple, no práctico. En particular, los nodos de lista no pueden ser recolectados como basura porque están enraizados por ProgramStartTime).

Esta clase 'ClockStamp' actúa como una lista enlazada inmutable, pero en realidad los nodos se generan a demanda para que puedan contener la hora 'actual'. Cualquier función que quiera medir el tiempo debe tener un parámetro 'clockStamp' y también debe devolver su última medición de tiempo en su resultado (para que la persona que llama no vea las mediciones antiguas), así:

// 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
}

Por supuesto, es un poco incómodo tener que pasar esa última medición dentro y fuera, dentro y fuera, dentro y fuera. Hay muchas maneras de ocultar el texto estándar, especialmente en el nivel de diseño del idioma. Creo que Haskell usa este tipo de truco y luego esconde las partes feas usando mónadas.




¡Sí! ¡Estás en lo correcto! Now () o CurrentTime () o cualquier firma de método de tal sabor no exhibe transparencia referencial de una manera. Pero mediante la instrucción al compilador, se parametriza mediante una entrada de reloj del sistema.

Por salida, Now () podría parecer que no sigue la transparencia referencial. Pero el comportamiento real del reloj del sistema y la función en la parte superior se adhiere a la transparencia referencial.




La mayoría de los lenguajes de programación funcionales no son puros, es decir, permiten que las funciones no solo dependan de sus valores. En esos idiomas, es perfectamente posible tener una función que devuelva la hora actual. De los idiomas que etiquetó esta pregunta con esto se aplica a scala y f # (así como a la mayoría de las demás variantes de ML).

En idiomas como Haskell y Clean, que son puros, la situación es diferente. En Haskell, la hora actual no estaría disponible a través de una función, sino de una llamada acción IO, que es la forma en que Haskell encapsula los efectos secundarios.

En Limpiar sería una función, pero la función tomaría un valor mundial como argumento y devolvería un nuevo valor mundial (además de la hora actual) como resultado. El sistema tipográfico se aseguraría de que cada valor mundial pueda usarse solo una vez (y cada función que consuma un valor mundial produciría una nueva). De esta forma, la función de tiempo tendría que invocarse con un argumento diferente cada vez y, por lo tanto, se le permitiría devolver una hora diferente cada vez.




Si es así, ¿cómo puede existir? ¿No viola el principio de la programación funcional? Viola particularmente la transparencia referencial

No existe en un sentido puramente funcional.

O si no, ¿cómo se puede saber la hora actual en la programación funcional?

En primer lugar, puede ser útil saber cómo se recupera un tiempo en una computadora. Básicamente, hay circuitos a bordo que registran el tiempo (que es la razón por la que una computadora generalmente necesita una batería de celda pequeña). Entonces podría haber algún proceso interno que establezca el valor del tiempo en un determinado registro de memoria. Que esencialmente se reduce a un valor que puede ser recuperado por la CPU.

Para Haskell, existe el concepto de una "acción IO" que representa un tipo que se puede realizar para llevar a cabo algún proceso IO. Entonces, en lugar de hacer referencia a un valor de time , hacemos referencia a un valor de IO Time . Todo esto sería puramente funcional. No estamos haciendo referencia al time sino a lo largo de las líneas de "leer el valor del registro de tiempo" .

Cuando realmente ejecutamos el programa Haskell, la acción IO tendría lugar en realidad.






Links