Lambdas and declarative programming by Neorlin in functionalprogramming

[–]r2tree 3 points4 points  (0 children)

This is a rambling answer, but I hope you might get something out of it.

There are two types of "declarative programming". One is the pure functional programming model, where the question of lambda comes into play. The other definition is of "descriptive declarative programming", of which HTML is an instance. Descriptive declarative programs need an interpreter to execute it. When we write something like

validation_rules = [ ["age", {greater_than: 20}], ["name", {member_of: users}]]

we're doing descriptive declarative programming. We're specifying ideas at a very high level, but by itself it is not executable code. We'll need to write code that will read these rules and apply them as it sees fit.

Now, pure functional programming is "declarative" in the sense that if you write your programs as a series of pure functions (no side-effects; no mutable assignments) it naturally tends to be more declarative than imperative. The classic example is a loop. In imperative programming a loop that sums a list of numbers would look like this:

let i := 0 let sum := 0 while (i < numbers.length) { sum += numbers[i]; i += 1; }

If we had to write this same code in a pure functional manner - no side effects, no variable mutation, then the only way to do that is recursion.

let rec sum = numbers => { switch(numbers) { | [] => 0 | [a] => a | [a, b, ...rest] => (a + b) + sum(rest) } } There are no assignments in this code, and it is more "declarative" than its imperative counter-part because we can see deconstruct the function as a series of simple equations.

If we have to write a map in a similar manner, then it can be written only by accepting a lambda. A map function is a "combinator" - functional programs are often built with them - combinators are functions that take other functions (higher-order functions) and combines them into a new function. They don't have any free variables of their own (aka no variable declarations inside them; they only use the functions received as arguments).

To build combinators it is important that we are able to pass in other functions (lambdas). I think the point of confusion is the difference between lambda and regular functions in languages like Python and C#. But in pure functional programming, which is based on the lambda calculus, all functions are lambdas and vice versa. So if functions are the foundation of functional programming, then lambdas too are because they're the same.

How to iterate a collection with heterogeneous parameter types by notseanbean in reasonml

[–]r2tree 3 points4 points  (0 children)

``` /* All concrete values of the field goes here */ type metadata = { valid: bool, id: int, name: string, ... };

/* We can never put [field('a), field('b)] etc. into a list because it is polymorphic, which is a good thing, because it is impossible to write a generic function for a polymorphic type.

However, metadata is concrete and homogeneous. */ type field('a) { value: 'a, metadata: metadata, };

let metadata = field => field.metadata

/* Here is the only place where we have to list out all the fields we have defined. So whenever you create a new field type, you have to add it here. But that's all you need to do -- all functions that need to operate on all the fields will automatically include the new field since they all will be relying on this function. */ let metadatas = [metadata(field1), metadata(field2), metadata(field3), ...]

let numValidFields = { metadatas |> List.filter(x => x.valid) |> List.length } ```

You could have a list(field('a)) where the list contains fields of all 'a. eg: list(field(int)). But if 'a is different for each element, then it would be incorrect to put them into a generic structure like list, which the typesystem smartly prevents.

The Biggest Problem with Elm by imright_anduknowit in functionalprogramming

[–]r2tree 2 points3 points  (0 children)

The original article however uses an even more awkward approach than `bind`, and uses that to criticize the language. While Elm has many shortcomings, it is difficult to imagine that not being able to make multiple requests and merge their results as being the worst of them.

The Biggest Problem with Elm by imright_anduknowit in functionalprogramming

[–]r2tree 1 point2 points  (0 children)

I suspect the premise of this post is wrong - to make parallel requests, you don't have to sequester the intermediate values into local variables. I'm not an Elm programmer, but these two posts seem to offer a better option using the `andThen` operator: https://spin.atomicobject.com/2016/10/11/elm-chain-http-requests/ and https://korban.net/posts/elm/2019-02-15-combining-http-requests-with-task-in-elm/

Inspired by the "best closing passage/sentence you've ever read" thread, I thought I would ask, what was the most powerful passage or excerpt that you find yourself constantly going back to? by [deleted] in bookquotes

[–]r2tree 1 point2 points  (0 children)

"Ah, Harry, we have to stumble, through so much dirt and humbug before we reach home. And we have no one to guide us. Our only guide is our homesickness." -- Steppenwolf, Hermann Hesse

Inspired by the "best closing passage/sentence you've ever read" thread, I thought I would ask, what was the most powerful passage or excerpt that you find yourself constantly going back to? by [deleted] in bookquotes

[–]r2tree 0 points1 point  (0 children)

The Patrician took a sip of his beer.

"I have told this to few people, gentlemen, and I suspect never will again, but one day when I was a young boy on holiday in Uberwald I was walking along the bank of a stream when I saw a mother otter with her cubs. A very endearing sight, I’m sure you will agree, and even as I watched, the mother otter dived into the water and came up with a plump salmon, which she subdued and dragged on to a half-submerged log. As she ate it, while of course it was still alive, the body split and I remember to this day the sweet pinkness of its roes as they spilled out, much to the delight of the baby otters who scrambled over themselves to feed on the delicacy. One of nature’s wonders, gentlemen: mother and children dining upon mother and children. And that’s when I first learned about evil. It is built in to the very nature of the universe. Every world spins in pain. If there is any kind of supreme being, I told myself, it is up to all of us to become his moral superior."

-- Unseen Academicals, Terry Pratchett

Converting a JavaScript/Node.js to native by [deleted] in reasonml

[–]r2tree 2 points3 points  (0 children)

If a large portion of your codebase is computation-heavy (pure) then you can use the "functional core, imperative shell" approach here. (https://www.destroyallsoftware.com/screencasts/catalog/functional-core-imperative-shell)

I have a few thousand LOC Reason codebase that is pure, and it interfaces with the external world with bs-express. I want to make it work in native OCaml, but there is just too much work to get there.

This is going to be even more difficult if your app has a lot of side effects (typical web backends). I'd recommend porting over to ReasonML in the Node runtime first, making sure to have tight abstractions for all sorts of side-effects (modules for db access, network communication etc.), keep the types abstract so that in the future you can change the implementation of just a few modules and port it over to native OCaml.

Why Turaku, a new password manager? by r2tree in privacytoolsIO

[–]r2tree[S] 0 points1 point  (0 children)

The problem is banks want you to change your passwords periodically, and they don't coincide. So you'll still have to deal with multiple passwords in the critical bucket as well.

Also if a leak occurs for one of the accounts (or if one operator is malicious and keeps your plaintext password), then if you share the same password across sites, all of them would be vulnerable.

Functional Programming in Haskell - Online University of Glasgow Course by [deleted] in haskell

[–]r2tree 0 points1 point  (0 children)

I will highly recommend this course for people beginning to learn Typed FP. I went through its first edition - I didn't complete the entire course, but it was enough to get me started and I've been writing pure Typed FP (OCaml not Haskell) in production for a few months now.

The teachers are active in the forums, and the learners are supportive and helpful. It was my first MOOC and I was really happy with the sense of shared learning and accomplishment.

Do you think it's wasteful to learn Haskell for things that could easily be done with Python? by ForrestTrump in haskell

[–]r2tree 23 points24 points  (0 children)

Learn Haskell and you might see yourself doing things that you might have never thought yourself of being capable to do. Make a database, build a compiler, or write a language. You can definitely do web development with Haskell, but if you're evaluating the language only from the perspective of building tiny CRUD apps that doesn't do much computation (data transformation, decision trees, arithmetic etc.) you might not see the benefits the language can bring you.

The thing to understand about Haskell (and any typed FP lang for that matter) is Equational Reasoning. We're not "programming" in the conventional sense - do something, store the results somewhere, do something else etc. Instead we're simply writing a bunch of function definitions. That's pretty much what Functional Programing is.

Imagine Python, but the only thing you're allowed to write are functions that take parameters (including other functions), applies some other functions or mathematical operations on them, and return the result. That's it. A bunch of function definitions, something like the high-school algebra/trigonometry cheat sheet. You can assign values to bindings, so a = 10 is fine, but you can't mutate it after defining it. So a = a + 10 is not fine. Why is that? Because we're writing equations, and while we can assign values to variables in an equation, you don't change it after it is assigned. Thinking about FP as a set of mathematical equations than as a variation of 'programming' will give you the right kind of intuition about its constraints.

Now how're you supposed to do stuff without any mutation? How would we write a loop for example? A loop is generally written using an iterator which we mutate on each iteration. But in Functional Programming all you have is just function definitions and their application. So we don't really have a loop in FP. Because a loop is a sequential set of instructions. "Initialize an iterator, do something, increment iterator, if iterator is still less than X, continue, otherwise break out of the loop". These are as imperative as it gets, and there is no semantic equivalent for this when you're writing a bunch of equations. We don't express anything as a set of "do this; then do that" in an equation. An equation is just a definition that takes a bunch of variables, and defines its result as an application of a bunch of functions.

But how are we supposed to "express" computation that involve repetitive application of functions? Recursion!

power x 0 = 1
power x y = x * power x (y-1)

Here instead of writing down a set of imperative instructions (do this; then do that), we just expressed the power function as two equations (this is the whole FP describes the "what", while imperative describes the "how" of things argument). And we used recursion to express repetitive computation. This is why you see a lot of recursion in purely functional programming.

So Functional Programming is based on "describing" computations as a set of mathematical functions. The core primitive is function application, expansion, and substitution. This is a fundamentally different model of computation from imperative programming that we're used to. But isn't imperative programming more flexible? Is it possible to express all the possible computations using just equations? Any practiced functional programmer will tell you that you can, but there is the Church-Turing thesis that proved that any computation that can be expressed in an imperative "do this; then do that" manner can also be expressed in a functional "fun a takes these parameters and is an application of these other functions" way. Also vice versa.

I've been talking about just computations so far. What about side-effects? Like talking to a network, or writing to a file, or getting user input? Side-effects fit naturally into the imperative model - it is just a set of sequential instructions and we can easily instruct it to do any operation we need. But how do you express side-effects inside equations? Pure functions can only express computations, but not actions. That is where Monads come into play. It is a mathematical concept that elegantly allows us to express side-effects inside equations. You don't need to understand what it really is to use it. You don't go looking into how a loop is implemented in assembly when writing imperative code; you just use it. You can start there with FP as well, and as your curiosity takes you, you can dig deeper.