Live data from Hacker News

Think in Math, Write in Code

justinmeiners.github.io

121–130 of 256 posts

Re: Think in Math, Write in Code

#121
post #62
post #14

Earlier quoted context omitted.

I think single letter variable names are fine within the scope of a single function. I don't. One of the things I like most about eslint is the id-length rule - https://eslint.org/docs/rules/id-length

I think it depends. In the context of a complex mathematical formula, where you have many intermediate results with very abstract meanings, I think it's more clear to use a single character name than to try to be descriptive with something like: `productOfLuminanceAndDotProductOfSurfaceNormalAndLightDirectionDividedByScatteringConstant`. I think there are a lot of advantages to abiding by styling conventions and usin…

Agreed. I'd much prefer something along these lines as opposed to using an overly long name:

`

/* product of luminance and dot product of surface normal and light direction divided by scattering constant */

const prod = ...

`

Re: Think in Math, Write in Code

#122
post #99

Earlier quoted context omitted.

I have found that the gap in understanding between thinking you understand something and implementing something as a program is often much smaller than the gap between having programmed something and having proven it.

What do you mean having proven it? As in you tested it and it works or do you mean you have formally using math that your solutions always gives the correct result? If it's the former then this is part of building it. An implementation without proper testing is incomplete. If it's the later I actually agree. Only the most sensitive of applications require that level of sophistication though.

A mathematical proof or analytical solution. I understand that analytical solutions only apply for very narrow ranges of problems but... consider writing an analytical solution to a differential equation versus applying a numerical solver. A numerical solution rarely leads to as deep an understanding as an analytical solution or a number of approximations in various limits. I feel like we're in the limit of something analogous to writing numerical solvers and claiming understanding from observing the output.

Re: Think in Math, Write in Code

#123
post #81

I honestly believe the majority of the problems in the industry comes from the refusal to treat programming as mathematics. Everything has to be "easy", so anyone can understand from a basic level. It's one of the reasons we don't like verifying software using TLA, coq(proofs for programs), refinement types or using functional programming techniques. "It's too difficult for the average programmer". The first excuse i…

Well, from a practical standpoint, it's more desirable to put out a partially-working system fast, which can be improved upon as it is live - than spend too much time planning and implementing a fully working system. Note: By partially and fully, I simply mean systems with more and less bugs. Rarely do companies and startups have the luxury to just lean back and take their time. It's a race against competitors, and e…

I agree that that is the pragmatic approach given market constraints, but the market is not providing greater value in driving this hack-and-patch approach.

Re: Think in Math, Write in Code

#125
post #7

It's not math, though. It's abstract reasoning, as is math. And that's about as deep as the similarities go. Math can't deal with imperfect input and/or side effects without turning into something else. And code without real world side effects is useless, as is real world perfection.

> Math can't deal with imperfect input and/or side effects without turning into something else. It very much can though.

Not in any sense that matters here, no.

There's no math equation for reading from a socket. Code is not math and math is not code. It's possible to sort of hide the fact by stacking enough abstractions on top, but in the end it's going to be the same old code that makes it happen.

Re: Think in Math, Write in Code

#126
post #35

As the author notes, Leslie Lamport makes much of the same point, but more rigorously. You can find it in many of his writings, e.g. http://lamport.azurewebsites.net/pubs/state-machine.pdf Lamport's TLA+ makes this formal. It is a language based on simple mathematics + some temporal logic for reasoning about discrete systems (software, hardware) as well as hybrid discrete-continuous systems, and is increasingly used…

For most programs, you can just use PlusCal instead of straight TLA+ and get most of the benefits. Unless you're writing something that is heavily concurrent or distributed.

I prefer TLA+ (it's both simpler and more powerful than PlusCal), except when specifying something at the code level (e.g. something like weak-memory-model concurrency algorithm).

Re: Think in Math, Write in Code

#127
post #77
post #66

Earlier quoted context omitted.

Math isn't formulas. The part of math that is most useful for programming are algebraic structures. Many "patterns", conventions, frameworks, etc., are just bastardizations of mathematical patterns. What really matters is the composition of concepts, and what better way to think about that than mathematically? So if you want your programming to reap the benefits of (others', mostly) mathematical reasoning--use a func…

> So if you want your programming to reap the benefits of (others', mostly) mathematical reasoning--use a functional language that is all about expressing the ways in which things compose! I do prefer using functional language over imperative ones, but I don't understand that is connected to model software on paper? > IO is modelled pretty well through monads. As are many other things, like nondeterministic processes…

> but I don't understand that is connected to model software on paper

I was talking more generally about techniques that allow for sneaking in mathematical thinking in various stages of development, not just modelling. Largely because of the very precise types which make a large part of your program verifiable (and force you to think about a lot of things you wouldn't have if you were using, say, JavaScript).

I was recently making a script engine for a game. It was really neat to realize that the "runScript" method was literally just a mapping between two monads. No special state inbetween, no complex logic, no file lookup or anything like that. These types of insight accumulate, and there's really a tonne of stuff to learn (this potential for learning the language itself feels much greater in functional programming for me).

> Isn't there any easier way to describe I/O than with category theory?

This isn't category theory! Do you really think every working Haskell programmer is some mathematician? No. Look at this random image I googled, you think Haskell programmers understand this? https://i.stack.imgur.com/4IzGk.png Most mathematicians don't!

The notion of a monad in functional programming might be inspired by category theory, but you're really better of not taking that connection too seriously. Functors, applicatives, and monads are all very simple notions that should be understood as programming constructs, not arcane math. If you want an area of math to research to most benefit your functional programming, that is undoubtedly mathematical logic and/or intro-level type theory, and not category theory. (This should take you in the direction of dependent types.)

Really, types are the key. The notion of a monad is best understood not through vague real-world analogies with sandwiches, but through the type and implementation of its >>= method. The reason for that is that the point of monads is in composition. And basic linear algebra is enough to understand the importance of composition, not category theory. Just look at the Maybe monad to immediately understand it: Nothing >>= f = Nothing, Just x >>= f = f x, where f : a -> Maybe b. Isn't this a really clear, intuitive way of composing operations which might fail?

Same goes for IO. The only thing you're doing is composing some values. When you compose an IO Int with some function of the type Int -> IO (), you get back a value of type IO () (which your runtime executes if you bind it to main). All of this is right in the type, and it's just as intuitive a way of composing IO values as Maybe ones, IMO.

You get the added benefit of execution becoming not a side-effect, but a first-class member. Evaluation of IO programs is not their execution, you could evaluate putStrLn "asdf" a million times without it being executed. You can literally store those programs (values) somewhere and execute them later.

Re: Think in Math, Write in Code

#128
post #65
post #63

How do I express my models of programs on paper that doesn't easily translate into math? I understand that the part of programs there you have a formula on beforehand (e.g., convert between Celsius and Fahrenheit) is easily expressed in a mathematical formula before implementing it. However, how should I express I/O? Often when I have a problem that isn't easily expressed in mathematical notation (albeit to my limite…

> However, how should I express I/O? First thing that comes to mind is category theory, especially monads. Haskell's I/O monad for example: https://en.wikipedia.org/wiki/Monad_(functional_programming)...

But why? Having to sweet talk the compiler into simply reading/writing data by building towers of super abstract mathematical concepts doesn't look like a win from here. If that's the cure, I'll take the disease.

Re: Think in Math, Write in Code

#129
post #88
post #33

Earlier quoted context omitted.

> Math can't deal with imperfect input and/or side effects without turning into something else. This is just not true. Differential equations certainly deal with change over time (except it's not called "side effects" there) and imperfections. The analog for discrete systems in temporal logic.

It's not called side effects there because there are none, in the modern mathematical formulation at least. The goal is to identify solution functions, and those are just sets of ordered pairs or something similarly inert.

Except that even in programming, the name "side-effect" is not too clear. It stems from the fact that subroutines sometimes behave a bit like functions, and when they don't, we call the added behavior a "side effect". If you want to be mathematically precise, subroutines are predicate transformers, and, again, there are no "side effects" (This is a mistake functional programmers make when they speak of referential transparency; most languages are referentially transparent, and that was the whole point of the paper that first introduced the term to programming. They are only not referentially transparent with respect to an incorrect semantic model). The philosophical difference between a subroutine with side effects and a derivative is small.

Re: Think in Math, Write in Code

#130
post #77
post #66

Earlier quoted context omitted.

Math isn't formulas. The part of math that is most useful for programming are algebraic structures. Many "patterns", conventions, frameworks, etc., are just bastardizations of mathematical patterns. What really matters is the composition of concepts, and what better way to think about that than mathematically? So if you want your programming to reap the benefits of (others', mostly) mathematical reasoning--use a func…

> So if you want your programming to reap the benefits of (others', mostly) mathematical reasoning--use a functional language that is all about expressing the ways in which things compose! I do prefer using functional language over imperative ones, but I don't understand that is connected to model software on paper? > IO is modelled pretty well through monads. As are many other things, like nondeterministic processes…

You don't need to know category theory. You just need to understand a few things that came from it, like `Maybe`, which is the most obviously useful and trivially easy monad. Just forget about the fact that it's a monad and any general rules about monads and just learn how to use `Maybe`.

From there, input handling is just a state machine. Easy to draw on paper as a graph.

> Part of the benefits with modelling a program on paper should be to make communication easier. And to require people you communicate with to have knowledge in category theory to understand your design fells silly.

This is an odd complaint, because you can also say: requiring people you communicate with to have knowledge in (state machines | graphs | `if` statements | ...) to understand your design feel silly.

Post reply on HN