Live data from Hacker News

Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

matt.might.net

21–30 of 51 posts

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#21
post #4

> Mathematics has no side effects. I'm aware the author is a professor of CS, but this is a statement I always see people originally trained as programmers claim, and as a mathematician and a programmer I respectfully disagree. Mathematics does what you define it to do, and if you can communicate your idea to another person it doesn't matter whether you "mutated" a variable or not. Likewise, you could say that there'…

One obvious example of a mutable variable is in math's very own expression of the for loop: n ∑ ƒ(i) i=m This implies a mutating variable (i) and a hidden mutating accumulator that tracks the sum. It seems like a perfectly clear mathematical expression of the concept, though, in spite of the fact that it is fraught with 'unmathematical' mutation. I can think of many mathematical algorithms which, when stated most sim…

Mathematicians arguably do not think of the first example as a loop with a mutating variable, but rather as a short-hand notation for f(m) + ... + f(n) - as a macro, if you wish.

I agree with the second part.

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#22
post #9

Earlier quoted context omitted.

I don't think anyone, mathematicians or functional programmers, have a problem with mutation [0]. They have a problem with names suddenly changing without being too explicit about that fact. In particular, mathematics certainly doesn't prohibit you from using whatever kind of notation you like to explain your concept, but it has suggested a certain primacy of the notion of a (pure) function. The reasons are both ones…

From a mathematicians perspective, functional programming languages do a fairly bad job at being able to express algorithms in the way mathematicians have been writing them down since before computers existed. There is little difference between writing $x_{k+1} = f(x_{k})$ and $x = f(x)$ in an imperative language. In some cases the index k can even be identified as a multiplicator of some discrete timestep, in which…

There is nothing destructive about the map M: A x A -> A.

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#23
post #4

> Mathematics has no side effects. I'm aware the author is a professor of CS, but this is a statement I always see people originally trained as programmers claim, and as a mathematician and a programmer I respectfully disagree. Mathematics does what you define it to do, and if you can communicate your idea to another person it doesn't matter whether you "mutated" a variable or not. Likewise, you could say that there'…

I always justify immutability by the fact that I like my assumptions not to change. I expect mathematicians to enjoy that property too.

ps : FP expresses changes as new instances with new parameters. Pushing away mutation as far as possible.

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#24
post #10
post #6

Earlier quoted context omitted.

> Likewise, you could say that there's no such thing as mutation in programs because the value of a variable in a language that supports mutation depends implicitly on time; you just don't express that in the source code. But this is precisely the problem with mutation and programming languages: ...some code... y = f(x) ...more code... z = g(x) Is x in the two lines the same? Often it's not. This is what's surprising…

I think what's surprising to a mathematician is if the fact that x can change is not stated prior to witnessing it. So you might say that immutability is a reasonable default for mathematics, but again not necessary as the author claims. While I think programmers might find it surprising, in mathematical proofs context is often the primary tool one uses to figure out what the hell is going on locally in some expressi…

> I think what's surprising to a mathematician is if the fact that x can change is not stated prior to witnessing it

This is precisely what happens in languages without immutability / control of mutation. They effectively say "this may or may not mutate. See for yourself. Oops! It just mutated. Sorry!"

Also, isn't what you talk about in your example just a shorthand to avoid cluttering a proof or whatever? It's not that variables mutate; it's that by convention you elide the notation that shows they mutate. That makes a lot of sense: the writer and the reader assume some things and go on with a compact notation that eliminates noise. It's a useful convention, and if the reader loses track of the notation, the worst that can happen is that he/she won't be able to understand the proof.

The problem with computer programs is that it's about both the reader and the computer interpreting the program. Because variables may or may not mutate, it's harder for the computer to perform some optimizations. Because of the same reason, it's harder for humans to understand the code ("is this going to use the convention that it won't mutate variables? I have to carefully read the code and consider all paths in order to be sure").

In a sense, programming with uncontrolled mutation is like switching the default convention to its most confusing setting :)

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#25

Earlier quoted context omitted.

From a mathematicians perspective, functional programming languages do a fairly bad job at being able to express algorithms in the way mathematicians have been writing them down since before computers existed. There is little difference between writing $x_{k+1} = f(x_{k})$ and $x = f(x)$ in an imperative language. In some cases the index k can even be identified as a multiplicator of some discrete timestep, in which…

There is nothing destructive about the map M: A x A -> A.

In fact there is, take A to be the space of differential forms on some manifold, and M the wedge product. Given two differential forms eta, mu, there is no way to recover eta and mu from M(eta,mu). Even simpler take two arbitrary numbers multiply them, unless they were prime you have no way of telling from the product what the two original numbers were. In other words multiplication destroys information.

In the case of numbers this is fine because there is in fact a way of copying them beforehand by an operation Delta : A -> A x A, which sends a number a to (a,a), so if given (a,b) you want both their product and the numbers themselves, you need a map A x A -> A x A x A given by (for example)

(id x M x id) . (id x id x Delta) . (Delta x id)

In the case of differential forms, there is no such (natural) map Delta.

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#26
post #4

> Mathematics has no side effects. I'm aware the author is a professor of CS, but this is a statement I always see people originally trained as programmers claim, and as a mathematician and a programmer I respectfully disagree. Mathematics does what you define it to do, and if you can communicate your idea to another person it doesn't matter whether you "mutated" a variable or not. Likewise, you could say that there'…

One obvious example of a mutable variable is in math's very own expression of the for loop: n ∑ ƒ(i) i=m This implies a mutating variable (i) and a hidden mutating accumulator that tracks the sum. It seems like a perfectly clear mathematical expression of the concept, though, in spite of the fact that it is fraught with 'unmathematical' mutation. I can think of many mathematical algorithms which, when stated most sim…

Dijkstra's shortest path: good point. There is obviously a purely functional implementation, but it's true that the most natural way of thinking about it involves assigning labels.

I disagree about the sum "loop". It's merely a notation, not an actual step by step operation. Unlike a traditional imperative language's variable, i's value cannot be changed. Whatever the actual expression of f, you know i is always the same within it. You could think of it this way: "for each value v from range m..n, introduce a new variable i at each step with value v, which we will use for the expression".

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#27

Earlier quoted context omitted.

There is nothing destructive about the map M: A x A -> A.

In fact there is, take A to be the space of differential forms on some manifold, and M the wedge product. Given two differential forms eta, mu, there is no way to recover eta and mu from M(eta,mu). Even simpler take two arbitrary numbers multiply them, unless they were prime you have no way of telling from the product what the two original numbers were. In other words multiplication destroys information. In the case…

What is your definition of "destructive"? A function with no inverse? Just trying to understand...

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#28
post #19

Earlier quoted context omitted.

From a mathematicians perspective, functional programming languages do a fairly bad job at being able to express algorithms in the way mathematicians have been writing them down since before computers existed. There is little difference between writing $x_{k+1} = f(x_{k})$ and $x = f(x)$ in an imperative language. In some cases the index k can even be identified as a multiplicator of some discrete timestep, in which…

I'm sadly not actually able to follow what you're getting at here. I think there are a few threads going on that I'd be interested in following up on, whether imperative/mutable semantics are common in mathematics, whether it makes sense to call something in abstract algebra as "destructive", what copying means, whether analyzing computational physics/numerics is a similar task, whether functional programming experts…

Perhaps a few points of clarification are in order, my original comment had too many different threads mixed together. I will first try to expand on my remarks on copying and then try to respond to some of the things you said.

When you look at the categories in use by mathematicians a surprisingly large number of them are not cartesian, this is true in particular of the categories relevant to physics, where both the category of symplectic manifolds (relevant to classical mechanics) and Hilbert spaces (relevant to Quantum Mechanics) are monoidal and not cartesian. In both cases you therefore can not copy states.

Moreover in physics things are local in the sense that the dynamics of a physical system is usually determined by differential equations. That means there is typically no situation where you have to retain much of the state of the system for a long time in order to simulate its behavior.

Even for complicated things like PDE simulations, what you really do is approximate some infinite dimensional function space locally with finite dimensional vector spaces. The state space in each step of the simulation is some tensor product. So while a computer certainly allows you to do it, it isn't really natural to constantly copy state in such simulations. Abstractly a Fortran 77 program could probably described by a collection of morphisms in some traced monoidal category, so it doesn't seem too far off from the mathematics it was invented to implement, although ultimately it clearly is deficient.

From a certain angle a lot of abstract algebra is actually more or less about creative destruction of information, certainly if you use it as a tool to study number theory, or topology. A whole class of functors there are monoidal functors from cartesian to non-cartesian categories and you carefully adjust how much information the functor loses in order to make computations feasible (Homology vs. Homotopy for example). The reason mutation doesn't seem to be prevalent, is because a lot of operations that are studied are invertible. But as soon as you for example study a group operation on a space, that is not faithful, then you won't be able to recover the original space after you've applied the group operation once, unless you've copied it before.

The connection between entropy and copying is fairly well explained in this paper I stumbled upon a while ago: http://www.pipeline.com/~hbaker1/ThermoGC.html

Of course the origins of copying in type theory is that for example Gentzen's calculus can be properly thought of as living in some cartesian closed category, as you probably know. Personally I find linear logic interesting, especially because it is able to faithfully embed intuitionistic logic and lets you talk precisely about copying. The problem is of course that type inference is undecidable for linear type theory, if I remember correctly.

In terms of expressive power Haskell is probably already fairly close to the ideal, most relevant to the discussions is I believe its inability to express laws its type classes have.

It is fairly good at expressing "free" or "cofree" things, but is not so good at expressing laws statically, not to mention providing a mechanism for proving the laws for instances. The best thing you can do is write embedded interpreters or compilers for those free / cofree things, that sort out things at runtime, or use template haskell.

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#29

This: public Node(SortedSet left, T element, SortedSet right) { this.left = left ; this.right = right ; this.element = element ; Isn't really mathematics. Nodes have a label. Any record attached to the node is business logic. It doesn't matter if the tuple is (first, last, address, department) or (value left, right), these are not part of the mathematics. Sure (value, left, right) looks like math, but it's just a con…

The article seems to be not-so-subtly hinting that Java is an anti-math programming language, and I agree. The language encourages each developer to reinvent and reimplement key concepts in terms of "classes" that are much more succinctly described in languages that embrace abstract algebra. The example of using inheritance and dynamic dispatch to represent a union type, is a perfect example.

Re: Translating Mathematics into Code: Examples in Java, Python, Haskell and Racket

#30
post #27

Earlier quoted context omitted.

In fact there is, take A to be the space of differential forms on some manifold, and M the wedge product. Given two differential forms eta, mu, there is no way to recover eta and mu from M(eta,mu). Even simpler take two arbitrary numbers multiply them, unless they were prime you have no way of telling from the product what the two original numbers were. In other words multiplication destroys information. In the case…

What is your definition of "destructive"? A function with no inverse? Just trying to understand...

Yes, not injective essentially, which is not the same as not having an inverse. The notion can be extended though, for example functors that aren't faithful are certainly destructive .
Post reply on HN