Thinking is functional. Creating a new array in Haskell / Purescript

I am new to functional programming and I decided to create an application in Purescript. I hit my first hurdle, and I'm not sure how to think about it conceptually.

I am not looking for code as a way to think functionally about this problem.

I have a list of data. In particular, something like

[ {a :: String, b :: String, c :: String} ] 

I would like to create an Html list (which is a purescript-halogen type) using the provided entry (with a list of the above types).

So I would have a function

 buildElements :: forall p i. MyRecordObject -> Array (HTML pi) 

Now I think that I will need to provide this result of the result of the function in the computational context of Monad (purescript Eff is similar to Haskell IO )

So something like:

 buildElements :: forall p i. MyRecordObject -> Eff (Array (HTML pi)) 

My first idea was vaguely around creating a list with something like

 take $ length xs $ repeat ARecordObject 

and then map the entry above this list, but I was not sure how to translate this into code. In any case, this was wrong, since my plan included a change in the state of ARecordObject , which does not matter.

So, I found this function:

 forEach :: forall e a. Array a -> (a -> Eff e Unit) -> Eff Unit 

which looks almost perfect! I get an array, I provide it with a function that somehow assigns the properties in the record to this new array ... but no, wait ... I think not functional again.

I really lost a little here. Basically, I want to create something like a list of <li></li> elements, where I assign properties to each element.

eg

I have a record:

 [ { id: "id1", name: "name1", class: "class1", content: "content1" } , { id: "id2", name: "name2", class: "class2", content: "content2" } ] 

And I need a foo function that returns an array:

 [ li [ id_ rec.id, name_ rec.name, class_ rec.class ] [ text rec.content ] , li [ id_ rec.id, name_ rec.name, class_ rec.lass ] [ text rec.content ] ] 

where rec is the name of the recordObject (and, obviously, the two arrays are not identical, but are actually mapped to the initial record).

(the dotted syntax is a syntax notation for a pyrex record similar to the standard getter / setter notation)

+5
source share
1 answer

My first idea was vaguely around creating a list with something like

 take $ length xs $ repeat ARecordObject 

and then display an entry on this list, but I was not sure how to translate this into code. In any case, this was wrong, since my plan included a mutation of the ARecordObject state, which does not matter.

Functional programmers do not just avoid mutations because they are no-no (indeed, many functional programs carefully use a controlled dose of variability) - we do this because it creates more secure and simple code.

In particular: you think what I call the "alloc-init mode" in which you create some kind of "empty" value, and then proceed to calculate its properties. Forgive my rigor, but this is a fundamentally broken programming model left over from manual memory management; the code that uses it will never be safe, and the abstractions that rely on it will forever flow. The idiom does not fit into any language that is taller than C, and yet, if I had a pound for every time I see such a code ...

 var foo = new Foo(); foo.Bar = new Bar(); foo.Bar.Baz = new Baz(); 

... I would be a rich man (na na na). By default, you need to create objects after you know how they will look:

 var foo = new Foo(new Bar(new Baz())); 

It’s simpler - you just calculate the value, and do not get into the memory referenced by the pointer to update its contents - and, more importantly, it is safer because the type checker ensures that you do not forget the property and this allows Foo immutable. The purest peremptory code is functional code β€” you must be required when it is necessary for performance (or when the language forces your hand).


In any case, rants. The fact is that you make life more difficult for yourself than you need, thinking imperatively. Just write a function that calculates one <li> from one object ...

 toLi :: MyRecord -> HTML toLi x = li [ id_ x.id, name_ x.name, class_ x.class ] [ text x.content ] 

... (note that I do not somehow create an "empty" li , and then fill in its values) and then map on your input list.

 toLis :: [MyRecord] -> [HTML] toLis = map toLi 

So I did it in JS, even if I don't need a language. No side effects, no mutation, no need for Eff - a simple, safe, purely functional code.

+15
source

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


All Articles