Utilice Kotlin para implementar Y-Combinator (Y-Combinator)

Utilice Kotlin para implementar Y-Combinator (Y-Combinator)

¿Podemos usar Kotlin FP (Lambda, función) para escribir una función de combinador Y?

Y = λf.(λx.f (x x)) (λx.f (x x))

Sabemos que en JS:

function Y(f) {
    
    
    return (function (g) {
    
    
        return g(g);
    })(function (g) {
    
    
        return f(function (x) {
    
    
            return g(g)(x);
        });
    });
}

var fact = Y(function (rec) {
    
    
    return function (n) {
    
    
        return n == 0 ? 1 : n * rec(n - 1);
    };
});

En café:

coffee> Y = (f) -> ((x) -> (x x)) ((x) -> (f ((y) -> ((x x) y))))
[Function]

coffee> fact = Y (f)  ->(n) -> if n==0 then 1 else n*f(n-1)
[Function]

coffee> fact(10)
3628800

En un lenguaje escrito dinámicamente, Y-Combinator es fácil de implementar.

Usando la interfaz de Java y la conversión de tipos también podemos lograr

public class YCombinator {
    
    

    public static Lambda<Lambda> yCombinator2(final Lambda<Lambda> f) {
    
    
        return ((Lambda<Lambda>)(Object input) -> {
    
    
            final Lambda<Lambda> u = (Lambda<Lambda>)input;
            return u.call(u);
        }).call(
            ((Lambda<Lambda>)(Object input) -> {
    
    
                final Lambda<Lambda> v = (Lambda<Lambda>)input;
                return f.call((Lambda<Object>)(Object p) -> {
    
    
                    return v.call(v).call(p);
                });
            })
        );

    }

    public static void main(String[] args) {
    
    
        Lambda<Lambda> y = yCombinator(
            (Lambda<Lambda>)(Object input) -> {
    
    
                Lambda<Integer> fab = (Lambda<Integer>)input;
                return (Lambda<Integer>)(Object p) -> {
    
    
                    Integer n = Integer.parseInt(p.toString());
                    if (n < 2) {
    
    
                        return Integer.valueOf(1);
                    } else {
    
    
                        return n * fab.call(n - 1);
                    }
                };
            });

        System.out.println(y2.call(10));//输出: 3628800
    }

    interface Lambda<E> {
    
    
        E call(Object input);
    }

}

Una implementación similar del combinador Y usando el paradigma de programación OOP de Kotlin es:

object YCombinatorKt {
    
    

    fun yCombinator(f: Lambda<Lambda<*>>): Lambda<Lambda<*>> {
    
    

        return object : Lambda<Lambda<*>> {
    
    

            override fun call(n: Any): Lambda<*> {
    
    
                val u = n as Lambda<Lambda<*>>
                return u.call(u)
            }
        }.call(object : Lambda<Lambda<*>> {
    
    

            override fun call(n: Any): Lambda<*> {
    
    
                val x = n as Lambda<Lambda<*>>

                return f.call(object : Lambda<Any> {
    
    
                    override fun call(n: Any): Any {
    
    
                        return x.call(x).call(n)!!
                    }
                })
            }

        }) as Lambda<Lambda<*>>
    }

    @JvmStatic fun main(args: Array<String>) {
    
    

        val y = yCombinator(object : Lambda<Lambda<*>> {
    
    

            override fun call(n: Any): Lambda<*> {
    
    
                val fab = n as Lambda<Int>

                return object : Lambda<Int> {
    
    

                    override fun call(n: Any): Int {
    
    
                        val n = Integer.parseInt(n.toString())
                        if (n < 2) {
    
    
                            return Integer.valueOf(1)
                        } else {
    
    
                            return n * fab.call(n - 1)
                        }
                    }
                }
            }
        })

        println(y.call(10)) //输出: 3628800
    }

    interface Lambda<E> {
    
    
        fun call(n: Any): E
    }
}

Por supuesto, Kotlin, que también es totalmente compatible con la programación funcional, también tiene una implementación de combinador Y estilo FP:


/**
 * Created by jack on 2017/7/9.
 *
 * lambda f. (lambda x. (f(x x)) lambda x. (f(x x)))
 *
 * FP YCombinator
 */

// 为了方便易懂,使用 X 用做函数 (X)->Int 的别名
typealias X = (Int) -> Int
// G 递归引用 G 自己
interface G : Function1<G, X>
// create a fun G from lazy blocking
fun G(block: (G) -> X) = object : G {
    
    
    // 调用函数自身 `block(g)` like as `g(g)`
    override fun invoke(g: G) = block(g)
}

typealias F = Function1<X, X>
fun Y(f: F) = (fun(g: G) = g(g))(G {
    
     g -> f({
    
     x -> g(g)(x) }) })

val fact = Y {
    
    
    rec ->
    {
    
    
        n ->
        if (n == 0) 1 else n * rec(n - 1)
    }
}
val fib = Y {
    
     f ->
    {
    
    
        n ->
        if (n == 1 || n == 2) 1 else f(n - 1) + f(n - 2)

    }
}


fun main(args: Array<String>) {
    
    
    println(fact(10))
    println(fib(10))

    for (i in 1..10) {
    
    
        println("$i!= ${
      
      fact(i)}")
    }

    for (i in 1..10) {
    
    
        println("fib($i) = ${
      
      fib(i)}")
    }
}


Entre ellos, la interfaz G hereda la interfaz Function1 <G, X>:

interface G : Function1<G, X>

La interfaz Function1 se hereda de kotlin. Interfaz de función:

public interface Function<out R>

Function1 tiene una invocación de función de operador abstracto, que se utiliza para llamar al parámetro de entrada p1:

public interface Function1<in P1, out R> : kotlin.Function<R> {
    public abstract operator fun invoke(p1: P1): R
}

Para la función G que definimos, el parámetro de entrada es la función de bloque (G) -> Xy el parámetro de entrada de la función de bloque es el tipo G. La función de invocación se usa para llamarse a sí misma:

fun G(block: (G) -> X) = object : G {
    // 调用函数自身 `block(g)` like as `g(g)`
    override fun invoke(g: G) = block(g)
}

De esta forma, podemos implementar una función de combinador Y:

typealias F = Function1<X, X>

fun Y(f: F) = (fun(g: G) = g(g))(G { g -> f({ x -> g(g)(x) }) })

Definimos la función recursiva factorial y la función de secuencia de Fibonacci a través del combinador Y:

val fact = Y {
    rec ->
    {
        n ->
        if (n == 0) 1 else n * rec(n - 1)
    }
}
val fib = Y { f ->
    {
        n ->
        if (n == 1 || n == 2) 1 else f(n - 1) + f(n - 2)

    }
}

Código de prueba:

fun main(args: Array<String>) {
    val square: X = { x -> x * x }
    println(square(9))

    println(fact(10))
    println(fib(10))

    for (i in 1..10) {
        println("$i!= ${fact(i)}")
    }

    for (i in 1..10) {
        println("fib($i) = ${fib(i)}")
    }
}

Proyecto de código fuente de Github: https://github.com/EasyKotlin/chapter8_fp


Comunidad de desarrolladores de Kotlin

Centrarse en compartir Java, Kotlin, Spring / Spring Boot, MySQL, redis, neo4j, NoSQL, Android, JavaScript, React, Node, programación funcional, ideas de programación, "alta disponibilidad, alto rendimiento, alto tiempo real" diseño de arquitectura de sistema distribuido a gran escala tema.

Diseño de arquitectura de sistema distribuido a gran escala de alta disponibilidad, alto rendimiento y tiempo real

Marco distribuido: Zookeeper, marco de middleware distribuido, etc.
Almacenamiento distribuido: GridFS, FastDFS, TFS, MemCache, redis, etc.
Base de datos distribuida: Cobar, tddl, Amoeba,
computación en la nube Mycat , big data,
virtualización de algoritmos de IA , nativos en la nube Tecnología
Marco informático distribuido: MapReduce, Hadoop, Storm, Flink, etc.
Mecanismo de comunicación distribuido: Dubbo, llamadas RPC, datos remotos compartidos, colas de mensajes, etc.
Cola de mensajes MQ: Kafka, MetaQ, RocketMQ
cómo construir un sistema de alta disponibilidad: basado en hardware, software Realización de algunas soluciones típicas como middleware y arquitectura de sistema: HAProxy, Corosync + Sistema de middleware de suite de clúster de alta disponibilidad basado en Pacemaker
Arquitectura Mycat evolución distribuida
Los problemas detrás de Big Data Join: contradicciones y reconciliación de datos, red, memoria y capacidades informáticas
Problemas de alto rendimiento en sistemas distribuidos Java: ¿AIO, NIO, Netty o frameworks de desarrollo propio?
Mecanismo de envío de eventos de alto rendimiento: modelo de grupo de subprocesos, modelo de disruptor, etc. . .

La madera que abraza nace al final del molino; la plataforma de nueve pisos comienza desde el sótano; el viaje de mil millas comienza con un solo paso. Si no acumula pasos, no puede llegar a mil millas; si no acumula pequeños arroyos, no puede convertirse en un río.

Introducción a Kotlin

Kotlin es un lenguaje que no es de investigación. Es un lenguaje de programación de grado industrial muy pragmático. Su misión es ayudar a los programadores a resolver problemas en la práctica real de la ingeniería. El uso de Kotlin mejora la vida de los programadores de Java. Los errores de puntero nulo en Java, el largo código repetitivo que desperdicia el tiempo, las restricciones de sintaxis detalladas, etc., desaparecen en Kotlin. Kotlin es simple y pragmático, con una sintaxis concisa y poderosa, segura y expresiva y extremadamente productiva.

Java nació en 1995 y tiene una historia de 23 años. La última versión actual es Java 9. En el proceso de desarrollo continuo y prosperidad del ecosistema JVM, también nacieron lenguajes hermanos como Scala, Groovy y Clojure.

Kotlin también es un excelente miembro de la familia JVM. Kotlin es un lenguaje moderno (la versión 1.0 se lanzó en febrero de 2016). Su propósito original es optimizar los defectos del lenguaje Java como Scala, proporcionar características de lenguaje de programación más simples y prácticas y resolver problemas de rendimiento, como el tiempo de compilación. JetBrains ha hecho un gran trabajo en estas áreas.

Características del lenguaje Kotlin

Después de desarrollar en Java durante muchos años, es genial poder probar algo nuevo. Si eres un desarrollador de Java, Kotlin será muy natural y fluido. Si es un desarrollador de Swift, se sentirá familiar, como Nullability. Las características del lenguaje Kotlin son:

1. Conciso

Reducir significativamente la cantidad de código repetitivo.

2. 100% de interoperabilidad con Java

Kotlin puede interactuar directamente con las clases de Java y viceversa. Esta característica nos permite reutilizar directamente nuestro código base y migrarlo a Kotlin. Porque la interoperabilidad de Java está en casi todas partes. Podemos acceder directamente a las API de la plataforma y las bases de código existentes, mientras disfrutamos y usamos todas las potentes funciones del lenguaje moderno de Kotlin.

3. Función de extensión

Kotlin es similar a C # y Gosu, brinda la capacidad de proporcionar nuevas extensiones funcionales para clases existentes sin tener que heredar de la clase o usar ningún tipo de patrones de diseño (como patrones decoradores).

4. Programación funcional

El lenguaje Kotlin primero admite programación funcional, al igual que Scala. Tiene características funcionales básicas como funciones de orden superior y expresiones lambda.

5. Parámetros predeterminados y con nombre

En Kotlin, puede establecer un valor predeterminado para los parámetros en una función y darle un nombre a cada parámetro. Esto ayuda a escribir código fácil de leer.

6. Soporte de herramientas de desarrollo de gran alcance

Y debido a que es producido por JetBrains, tenemos una excelente compatibilidad con IDE. Aunque la conversión automática de Java a Kotlin no es 100% correcta, de hecho es una muy buena herramienta. Cuando se utilizan las herramientas de IDEA para convertir código Java a código Kotlin, el 60% -70% del código resultante se puede reutilizar fácilmente y el costo de modificación es pequeño.

Además de sus características de sintaxis concisas y poderosas, Kotlin también tiene una API muy práctica y un ecosistema construido a su alrededor. Por ejemplo: API de colección, extensión IO, API de reflexión, etc. Al mismo tiempo, la comunidad de Kotlin también proporciona una gran cantidad de documentos y muchos materiales de aprendizaje, así como REPL en línea.

Un lenguaje de programación moderno que hace más felices a los desarrolladores. Código abierto para siempre

Imagen de "Kotlin desde la entrada al combate avanzado" (Chen Guangjian, Tsinghua University Press)

Imagen de "Kotlin desde la entrada al combate avanzado" (Chen Guangjian, Tsinghua University Press)

https://kotlinlang.org/

Supongo que te gusta

Origin blog.csdn.net/universsky2015/article/details/108669514
Recomendado
Clasificación