Considering the name of the drawing visible in Elm, and if other similar cases

I am currently an FP student. When I look at various syntax sentences in different functional languages, I came across a template in the Elm code example. I'm interested.

Here is a sample code

myList = [{foo = "bar1"},{foo = "bar2"}] foos = myList |> List.map .foo 

In the last line here List.map is passed .foo . I believe this style is called indifferent, but what about the specific transfer pattern in the List.map function List.map ?

Is this a more common thing? Is it possible to do this in Haskell? F #? Scala? Thanks for any help.

What is (or is) a formal (or informal?) Name for the template here? Is an object property used as a short hand for a function that takes an object and calls the specified property on it?

+5
source share
2 answers

In fact, this is not a point, but syntactic sugar and a straight pipe operator. For a free point, see this article .

This can be written in fsharp as follows:

let foos = myList |> List.map (fun x -> x.foo)

And you will immediately see that it is equivalent

List.map (fun x -> x.foo) myList

Thus, the pipe operator simply reverses the arguments and simplifies the chain of operations. This way you pass your function and list to the map. And Elm's syntactic sugar allows you to skip a function parameter, just buy .foo writing. I find this feature very handy by the way.

Without points, you can avoid specifying function parameters. This is a typical FP, but it is hard to read once it gets complicated.

Example:

 let mySum xy = x + y //val mySum : x:int -> y:int -> int mySum 4 7 //11 

It's free:

 let mySum2 = (+) //val mySum2 : (int -> int -> int) mySum2 4 7 //11 
+7
source

If you consider your list as a “data set” or “table” and consider each element in the list as a “row” and determine the data type of the elements as an enumeration of “attributes”, then what you get is a kind of “projection” in the sense of relational algebra : https://en.wikipedia.org/wiki/Projection_(relational_algebra) .

Here is an example of a Scala -example that senses multiple SQLs:

 case class Row(id: Int, name: String, surname: String, age: Int) val data = List( Row(0, "Bob", "Smith", 25), Row(1, "Charles", "Miller", 35), Row(2, "Drew", "Shephard", 45), Row(3, "Evan", "Bishop", 55) ) val surnames = data map (_.surname) val ages = data map (_.age) val selectIdName = data map { row => (row.id, row.name) } println(surnames) // List(Smith, Miller, Shephard, Bishop) println(selectIdName) // List((0,Bob), (1,Charles), (2,Drew), (3,Evan)) 

Here _.fieldName is a short syntax for a string literal of a function of type Row => TypeOfTheField .

In Haskell, this is somewhat trivial because declaring a record data type automatically puts all getter functions in scope:

 data Row = Row { id :: Int , name :: String , surname :: String , age :: Int } deriving Show main = let dataset = [ Row 0 "Bob" "Smith" 25 , Row 1 "Charles" "Miller" 35 , Row 2 "Drew" "Shephard" 45 , Row 3 "Evan" "Bishop" 55 ] in print $ map name dataset -- prints ["Bob","Charles","Drew","Evan"] 

Even Java has something similar since version 8:

 import java.util.*; import java.util.stream.*; import static java.util.stream.Collectors.*; class JavaProjectionExample { private static class Row { private final int id; private final String name; private final String surname; private final int age; public Row(int id, String name, String surname, int age) { super(); this.id = id; this.name = name; this.surname = surname; this.age = age; } public int getId() { return this.id; } public String getName() { return this.name; } public String getSurname() { return this.surname; } public int getAge() { return this.age; } } public static void main(String[] args) { List<Row> data = Arrays.asList( new Row(0, "Bob", "Smith", 25), new Row(1, "Charles", "Miller", 35), new Row(2, "Drew", "Shephard", 45), new Row(3, "Evan", "Bishop", 55) ); List<Integer> ids = data.stream().map(Row::getId).collect(toList()); List<String> names = data.stream().map(Row::getName).collect(toList()); System.out.println(ids); System.out.println(names); } } 

Here Row::getterName is a special syntax for getter methods, it is a value of type Function<Row, FieldType> .

+8
source

Source: https://habr.com/ru/post/1275026/


All Articles