sirven relacionales que programacion para operadores los logicos ejemplos aritmeticos elm

elm - que - operadores relacionales ejemplos



¿Qué significa el operador `<<` en olmo? (5)

Es función composición. Para su ejemplo concreto significa

/x -> (Signal.send updateChan (toUpdate x))

En elm no es parte de la sintaxis sino parte de la biblioteca estándar: Basics.<<

En el siguiente código tomado de Elm Form Example , línea 122, ¿qué significa el operador << ?

Field.field Field.defaultStyle (Signal.send updateChan << toUpdate) "" content

No se pudo encontrar en la referencia de sintaxis de Elm .

¿Significa que, cuando el campo cambia, en lugar de enviar su content a updateChan , enviar a toUpdate a updateChan ?


Explantion para desarrolladores de javascript :

--elm (a << b) x

Será similar

//javasript a(b(x))

<< o >> se llama composición de funciones


Mi segundo intento: D

<< vs <|

La diferencia entre << y <| es que << se usa para componer funciones y <| se usa para omitir paréntesis.

Por qué funciona así

Veamos la anotación de tipo que se encuentra here :

<< : (b -> c) -> (a -> b) -> a -> c

Esta definición nos dice que cuando pasa dos funciones a la función << , obtendrá la función a -> c .

Ejemplo con demo

hi a = a + 2 hello a = a * 2 bye = hello << hi c = bye 3

c devuelve el valor 10 .

Leer más sobre:


<< es un operador de composición de funciones, definido en los conceptos Basics biblioteca principal. Todas las funciones de Basics se importan a proyectos de Elm sin calificar.

Sistema de tipos de Elm

Recordemos los conceptos básicos del sistema de tipo Elm.

Elm está estáticamente escrito . Esto significa que en Elm cada variable o función tiene un tipo, y este tipo nunca cambia. Ejemplos de tipos en Elm son:

  • Int
  • String
  • Maybe Bool
  • { name : String, age : Int }
  • Int -> Int
  • Int -> String -> Maybe Char .

La escritura estática significa que el compilador garantiza que los tipos de todas las funciones y variables son correctas durante la compilación, por lo que no tiene errores de tipo de tiempo de ejecución. En otras palabras, nunca tendrá una función de tipo String -> String recibe o devuelve Int , código que permite que esto ni siquiera se compile.

También puede hacer que sus funciones sean polimórficas reemplazando un tipo concreto como String o Maybe Int con una variable de tipo, que es una cadena minúscula arbitraria, como a . Muchas funciones principales de Elm son de tipo polimórfico, por ejemplo List.isEmpty tiene el tipo List a -> Bool . Toma una List de algún tipo y devuelve un valor de tipo Bool .

Si vuelve a ver la misma variable de tipo, las instancias de esta variable de tipo deben ser del mismo tipo. Por ejemplo, List.reverse tiene el tipo List a -> List a . Entonces, si aplica List.reverse a una lista de enteros (es decir, a algo que tiene el tipo List Int ), devolverá una lista de enteros. De ninguna manera dicha función puede tomar una lista de enteros, sino devolver una lista de cadenas. Esto está garantizado por el compilador.

Todas las funciones en Elm se curried por defecto. Esto significa que si tiene una función de 2 argumentos, se transforma en una función de 1 argumento que devuelve una función de 1 argumento. Es por eso que la sintaxis de aplicación de función de Elm es tan diferente de la aplicación de función en otros lenguajes como Java, C ++, C #, Python, etc. No hay razón para escribir someFunction(arg1, arg2) , cuando puede escribir someFunction arg1 arg2 . ¿Por qué? Porque en realidad someFunction arg1 arg2 es en realidad ((someFunction arg1) arg2) .

El curry hace posible la aplicación parcial . Suponga que desea aplicar parcialmente List.member . List.member tiene un tipo a -> List a -> Bool . Podemos leer el tipo como " List.member toma 2 argumentos, de tipo a y tipo List a ". Pero también podemos leer el tipo como " List.member toma 1 argumento de tipo a . Devuelve una función de tipo List a -> Bool ”. Por lo tanto, podemos crear una función isOneMemberOf = List.member 1 , que tendrá el tipo List Int -> Bool .

Esto significa que -> en el tipo de anotaciones de funciones es derecho-asociativo. En otras palabras, a -> List a -> Bool es lo mismo que a -> (List a -> Bool) .

Notación de infijo y prefijo

Cualquier operador infijo es en realidad una función ordinaria detrás de las cortinas. Es justo cuando el nombre de una función consiste únicamente en símbolos no alfanuméricos (como $, <|, <<, etc.), se coloca entre 2 argumentos, no delante de ellos (como las funciones ordinarias).

Pero aún puede poner un operador binario como + delante de los 2 argumentos, encerrándolo entre paréntesis, por lo que las 2 aplicaciones de funciones a continuación son equivalentes:

2 + 3 -- returns 5 (+) 2 3 -- returns 5, just like the previous one

Los operadores de infijo son solo funciones ordinarias. No hay nada especial en ellos. Puede aplicarlos parcialmente como cualquier otra función:

addTwo : Int -> Int addTwo = (+) 2 addTwo 3 -- returns 5

Composición de la función

<< es un operador de composición de funciones, definido en los conceptos Basics biblioteca principal. Todas las funciones de los elementos básicos se importan en proyectos de Elm sin calificar, lo que significa que no tiene que escribir import Basics exposing (..) , ya está hecho de forma predeterminada.

Entonces, como cualquier otro operador, (<<) es solo una función, como cualquier otra. Cual es su tipo

(<<) : (b -> c) -> (a -> b) -> a -> c

Porque -> es asociativo a la derecha, esto es equivalente a:

(<<) : (b -> c) -> (a -> b) -> (a -> c)

En otras palabras, (<<) toma 2 funciones de los tipos b -> c y a -> b respectivamente, y devuelve una función del tipo a -> c . Compone 2 funciones en una. ¿Cómo funciona? Veamos un ejemplo artificial por simplicidad. Supongamos que tenemos 2 funciones simples:

addOne = (+) 1 multTwo = (*) 2

Supongamos que no tenemos (+) , solo addOne , ¿cómo crearíamos una función que agregue 3, no 1? Muy simple, compondríamos addOne juntos 3 veces:

addThree : Int -> Int addThree = addOne << addOne << addOne

¿Qué sucede si queremos crear una función que agregue 2 y luego se multiplique por 4?

ourFunction : Int -> Int ourFunction = multTwo << multTwo << addOne << addOne

(<<) compone funciones de derecha a izquierda. Pero el ejemplo anterior es simple, porque todos los tipos son iguales. ¿Cómo encontraríamos una suma de todos los cubos pares de la lista?

isEven : Int -> Bool isEven n = n % 2 == 0 cube : Int -> Int cube n = n * n * n ourFunction2 : List Int -> Int ourFunction2 = List.sum << filter isEven << map cube

(>>) es la misma función, pero con los argumentos invertidos, por lo que podemos escribir la misma composición de izquierda a derecha:

ourFunction2 = map cube >> filter isEven >> List.sum

Resumen

Cuando ves algo como h << g << f , entonces sabes que f , g , h son funciones. Cuando esta construcción h << g << f se aplica a un valor x , entonces sabes:

  • Elm primero aplica f a x
  • luego aplica g al resultado del paso anterior
  • luego aplica h al resultado del paso anterior

Por lo tanto (negate << (*) 10 << sqrt) 25 es igual a -50.0 , porque primero toma una raíz cuadrada de 25 y obtiene 5, luego multiplica 5 por 10 y obtiene 50, luego niega 50 y obtiene -50.

¿Por qué << y no?

Antes de Elm 0.13 (ver announcement ), el operador de composición de funciones era (.) , Y su comportamiento era idéntico al actual (<<) . (<<) se adoptó en Elm 0.13 del lenguaje F # (vea el tema de Github ). Elm 0.13 también agregó (>>) como equivalente a flip (<<) y (<|) como reemplazo del operador de aplicación de función ($) , y (|>) como equivalente a flip (<|) .

Llamada de función infija

Tal vez se pregunte si puede convertir un nombre de función alfanumérico ordinario en un operador binario infijo. Antes de Elm 0.18, usaría los backticks para hacer una función infija, por lo que debajo de 2 sería equivalente:

max 1 2 -- returns 2 1 `max` 2 -- returns 2

Elm 0.18 eliminó esta característica . Ya no puedes hacerlo en Elm, pero los lenguajes como Haskell y PureScript todavía lo tienen.


<< es una composición de función - devuelve función.

La composición crea una tubería de cálculos, una cadena de funciones. Esta tubería espera la entrada, y cuando se proporciona, la primera función comienza el cálculo, envía la salida a la siguiente, etc.

import Html add x y = Debug.log "x" x + Debug.log "y" y add9 = add 4 << add 5 main = Html.text <| toString <| add9 2

Nota : En el ejemplo anterior, uso una aplicación parcial . Significa que no proporciono todos los parámetros para funcionar y, como resultado, obtengo la función.

Si ejecuta el ejemplo anterior en el navegador web y mira la salida de la consola, verá:

x: 5 y: 2 x: 4 y: 7

Si lo escribimos como operaciones matemáticas, se verá así:

4 + (5 + 2) 4 + 7

Nota : También podemos usar la versión directa >> .

Lectura de firmas

Mirando la firma de este operador:

(<<) : (b -> c) -> (a -> b) -> a -> c

Para el operador << , hay una función b -> c como primer parámetro, y una función a -> b como segundo:

(b -> c) << (a -> b)

Pero también hay un tercer parámetro a . Porque -> es derecho-asociativo, entonces

(<<) : (b -> c) -> (a -> b) -> a -> c

es equivalente a:

(<<) : (b -> c) -> (a -> b) -> (a -> c) .

De modo que << devuelve la función a -> c .

Asociatividad

En lenguajes de programación, la asociatividad (o fijeza) de un operador es una propiedad que determina cómo se agrupan los operadores de la misma precedencia en ausencia de paréntesis; es decir, en qué orden se evalúa cada operador:

a = b = c se analiza como a = (b = c)

Operador infijo

Aquí uso << como operador de infijo , pero también podemos usarlo como operador de prefijo encerrándolo entre paréntesis: (<<) (b -> c) (a -> b) o (<|) (add 4) (add 5) .

elm <0.18 solía permitirte tomar funciones normales y usarlas como operadores infijos.

Una palabra sobre <| operador

<| es una aplicación de función - devuelve valor

Básicamente lo usamos en lugar de paréntesis.

text (something ++ something)

Se puede escribir como

text <| something ++ something

Mirando la firma de este operador:

(<|) : (a -> b) -> a -> b

podemos ver eso para <| operador, hay una función a -> b como primer parámetro, y el valor a como segundo:

(a -> b) <| a

y vuelve b .

Podemos obtener el mismo valor con la aplicación de función <| :

v1 = add 4 <| add 5 <| 4 v2 = (add 4 << add 5) 4