Hacker Newsnew | past | comments | ask | show | jobs | submit | discarded1023's commentslogin

I had a look at George Stiny's "Shape: Talking about Seeing and Doing" book (MIT Press, 2006) which is freely available on the web [1]. The introduction is very waffly ... his analysis of shape strikes me as what Euclid('s predecessors) did a long time ago in figuring out what geometry should talk about. Combining primitive images/shapes algebraically was explored by Henderson in the early 1980s [2] and many others; SICP too IIRC.

Has anyone used this stuff (shape grammars) in anger? Any pointers to a system that works on current platforms that is worth playing with?

[1] https://web.archive.org/web/20140105105101/http://shapetalki...

[2] https://dl.acm.org/doi/pdf/10.1145/800068.802148


There's a tonne of work done in this space, e.g. Mary Sheeran's µFP from the early 1980s [1], at least for classical synchronous digital circuits. Some googling will dig up a survey or two on modelling circuits with functions and a variety of systems in various languages. BlueSpec was and perhaps is interesting too but is quite a different approach.

[1] see e.g. https://www.jucs.org/jucs_11_7/hardware_design_and_functiona...


> We can't prove that the axioms of arithmetic are consistent [...]

Sure we can! [1] ... but it requires (logically) stronger axioms. Assessing the relative strength of axioms along these (Gentzen's) lines goes by the name "ordinal analysis". It's not clear to me that stronger axioms are always less plausible than weaker ones (as axioms).

An alternative is to abandon your insistence on consistency. Another thread points to an article by Graham Priest but not to one of his main research interests: paraconsistency. This line of work aims to route around these issues (paradox in general) by making inconsistencies less explosive. A quick google turned up some relevant discussion [2]. I have it on good authority that the wheels fall off at some point.

[1] https://en.wikipedia.org/wiki/Gentzen%27s_consistency_proof

[2] https://math.stackexchange.com/questions/1524715/how-do-inco...


> We can't prove that the axioms of arithmetic are consistent

using the axioms themselves. We can prove consistency using a stronger set of axioms, but those axioms have their own liar sentence, and so they can't prove their own consistency. And without knowing if the stronger set of axioms is consistent, we can't be sure that we have really proved the consistency of arithmetic.


For those looking for a broader/more portable introduction, Xavier Leroy and Didier Rémy wrote a great high-level text on UNIX system programming a long time ago [1]. Of course it uses ocaml (perhaps motivating some to learn that language) but the style is low-level and straightforwardly imperative. The advantage is that it sweeps up a lot of the messy and boring error handling into the ocaml runtime and/or exceptions. This makes the code a lot easier to follow, but of course makes it look misleadingly simpler than it would be in C (etc).

[1] https://ocaml.github.io/ocamlunix/


Why would someone want to learn Unix Programming using OCAML? Not a smart choice. Also this does not look easier to read than a shell script either.

let rec copy_rec source dest = let infos = lstat source in match infos.st_kind with | S_REG -> file_copy source dest; set_infos dest infos | S_LNK -> let link = readlink source in symlink link dest | S_DIR -> mkdir dest 0o200; Misc.iter_dir (fun file -> if file <> Filename.current_dir_name && file <> Filename.parent_dir_name then copy_rec (Filename.concat source file) (Filename.concat dest file)) source; set_infos dest infos | _ -> prerr_endline ("Can't cope with special file " ^ source)


[flagged]


IMHO modern C (with modern tooling) is very reasonable.


Thanks! I just started the OCaml Programming Book this week to learn and language and get better at functional programming. Cant wait to jump into this after


There were plans to build a hydrogen plant near Whyalla in South Australia, a famous steel-making site; see e.g. [1]. The tl;dr uses were export (I expected ammonia but the whole thing was vague enough to include hydrogen) on boats, reduction of iron ore ("decarbonisation", apparently requires magnetite) and while all the financial engineering that didn't happen was going to happen, energy storage for the grid, soaking up S.A.'s over-abundant solar.

Someone observed that this was the entirety of the presently-outgoing (but sure to be re-elected) state regime's story about reducing electricity bills in the state.

[1] https://research.csiro.au/hyresource/south-australian-govern...


Here's another from a long time ago: https://dkeenan.com/Lambda/


I like this catalog: https://github.com/prathyvsh/lambda-calculus-visualizations

And it seems that John Tromp's diagrams originate from David C. Keenan's Mockingbird (1996),

and Bubble Notation comes from Wayne Citrin's Visual Expressions (1995)


Thanks for the link! Some very pretty stuff there.

Missing AFAICT are categorical string diagrams. I'm only sort-of familiar with the notation for Haskell Arrows [1,2] but a quick google for "lambda calculus string diagrams" turns up some recent work by Dan Ghica and others that may be of interest.

[1] https://en.wikipedia.org/wiki/String_diagram

[2] Ross Paterson "A New Notation for Arrows" (2001)


Thanks! I liked the pics here: https://piedeleu.com/posts/diagrammatic-lambda-calculus/

I'd love to see them smoothly animated.


If we're going down that path: Ehud Shapiro got there back in 1984 [1]. His PhD thesis is excellent and shows what logic programming could do (/could have been).

He viewed the task of learning predicates (programs/relations) as a debugging task. The magic is in a refinement operator that enumerates new programs. The diagnostic part was wildly insightful -- he showed how to operationalise Popper's notion of falsification. There are plenty of more modern accounts of that aspect but sadly the learning part was broadly neglected.

There are more recent probabilistic accounts of this approach to learning from the 1990s.

... and if you want to go all the way back you can dig up Gordon Plotkin's PhD thesis on antiunification from the early 1970s.

[1] https://en.wikipedia.org/wiki/Algorithmic_program_debugging


At the risk of telling you what you already know and/or did not mean to say: not everything can be a value. If everything is a value then no computation (reduction) is possible. Why? Because computation stops at values. This is traditional programming language/lambda calculus nomenclature and dogma. See Plotkin's classic work on PCF (~ 1975) for instance; Winskel's semantics text (~ 1990) is more approachable.

Things of course become a lot more fun with concurrency.

Now if you want a language where all the data thingies are immutable values and effects are somewhat tamed but types aren't too fancy etc. try looking at Milner's classic Standard ML (late 1970s, effectively frozen in 1997). It has all you dream of and more.

In any case keep having fun and don't get too bogged in syntax.


IMHO this is both unnecessarily pedantic and not really quite right. Let’s say we accept the premise that “everything is a value” means reduction is impossible. But a value is just the result of reducing a term until it is irreducible (a normal form). So if there is no reduction there can’t really be values either—there is just “prose” (syntax) and you might as well read a book.


I am unable to extract any meaning from your post. You appear to be making a general claim: it is impossible to design a programming language where everything is a value. You at least admit that "data thingies" can be values. Are you claiming that it is not possible for functions to be values? (If we assume that the argument and the result of a function call is a value, then this would mean higher order functions are impossible, for example.) If not that, then what? Please give a specific example of something that can never be a value in any programming language that I care to design.


I think parent means it from a lambda calculus perspective. If you only have values at an AST level, then you only have a tree of.. values, like an XML document.

You can apply meaning to a particular shape of that tree which could be executed, but then you basically just added another layer before you parse your AST that becomes executable.


Thanks, some interesting reading there that I will check out (I wasn't aware of PCF). Perhaps I should've used more precise wording: "All types are value types".

> Standard ML [...] It has all you dream of and more

The main thing here that's missing in Standard ML (and most other functional languages) is the "mutable" part of "mutable value semantics" - i.e., the ability to modify variables in-place (even nested parts of complex structures) without affecting copies. This is different from "shadowing" a binding with a different value, since it works in loops etc.


Quick note then a more wordy response (and after being dinged in another thread yesterday, the tl;dr is your usage is correct, ignore purposely avoiding context criticism of wording):

SML has mutation, but only for Ref Cells, which humorously are values themselves. Not that’s what you’re really talking about here.

Now for the wordy part…

As another of your sibling commenters said GP was being incredibly pedantic. While his reference to Plotkin/Winskel and the PCF thread of research is formative, it is of particular note for Structural Operational Semantics.

The real issue GP is raising that in programming language semantics there are two distinct ways in which the term ‘value’ is used. Worse still is that the terms are not just distinct but are broadly from two very distinct fields in PLT. So, what are the two uses:

  1) when the domain of discourse is Operational Semantics of Programming Languages, a ‘value’ is a term in the formal abstract syntax of the language which is not subject to reduction via any other transition defined over the syntax;

  2) when the domain of discourse is the Evaluation and Default Kinds of arguments passed to functions and the semantic implications of those defaults, a ‘value’ is defined in the negative as those semantic objects which ARE NOT references [1];
which from the definitions alone, it is clear your designation of your language as ‘pass-by-value’ is a distinct thing from GP’s usage of the term.

While GP’s usage of ‘value’ is in line with a long standing tradition, that tradition is firmly within the academic/functional programming language syntax and semantics sphere. Your usage, as is PLAINLY APPARENT from context, is absolutely correct and in line with long standing usage within discussion (and academic work) on imperative (and otherwise non-functional) programming language semantics. So keep phrasing discussions about Herd using the ‘pass-by-value’ and ‘everything is a value’. It’s not only contextually correct and historically justified, it is utterly within the ‘vernacular’ of normal programming language discussions.

One last thought, your language’s adoption of totally defaulting to passing arguments (to functions, threads, basically any control construct), with copy-on-write being an optimization only, should make implementing a non-reified linearity qualifier on types relatively simple to implement, that would address some of the locking anti-optimizations and address some of your static analysis that you mentioned where not working 100%.

———————

1: Reference here include Rust/C++ style lightly abstracted references, nearly zero abstraction pointers, and then the references as discussed when talking about Python, Ruby, JavaScript, C++ smart pointers, Rust’s higher level abstractions over references, etc which are a very abstract concept of reference.


Excuse me if I didn't get it right, but as a practical example, I'd assume that I can rewrite every program into JavaScript using the usual control structures and, beyond that, nothing but string values (which are immutable). Simple arithmetic would already be kind of a chore but can be done. (Input and output already happens only via serialized values (cf also webworkers) so there's that; for convenience use TypedArrays wrapped in classes that shield you from immutability). It is not obvious to me where `a = '[1,2]'; a1 = JSON.stringify( JSON.parse( a ).push( 3 ) ) );` is fundamentally different from just pushing a value to a copy of `a`. Also, you could write `a1 = a.slice(0,-1) + '3]'` which only uses non-mutating stuff under the hood.


Where do Hughes's Arrows fit in?


In this particular case, Hughes’ arrows are a practical implementation of a Profunctor Categorical Structure. They are roughly a generalization of what arrows (as in function types or more accurately relations) are.

In the article, author is pointing out that the selective applicative doesn’t seem to work correctly (in a categorical sense) for functions, but when generalizing to profunctors a near semi-ring structure appears and works for the SApplicative.

I am pretty sure I’m reading TFA correctly here, but I’ll check when off mobile and edit if I still can.


You'd like to know your fault tolerance is reliable and possibly even correct.


Not if proving so is more expensive to do than not. Reliability is only a means. Not the end. Also the human parts of the business would need to be simplified in order to model them. If deviate from the model that could invalidate it.


Agree on the economics. I’m not arguing for full formal proofs; I’m arguing for low-cost enforcement of invariants (ADTs/state machines/exhaustiveness) that makes refactors safer and prevents silent invalid states. Human processes will always drift, so you enforce what you can at the system boundary and rely on reconciliation/observability for the rest.


In the banking subdomain of credit/debit/fleet/stored-value card processing, over time when considering regulation and format evolution, services provided by banks/ISOs/VARs will effectively exhibit FP traits regardless the language(s) used to implement them.

Savvy processors recognize the immutability of each API version published to Merchants, along with how long each must be supported, and employ FP techniques both in design and implementation of their Merchant gateways.

Of course, the each bank's mainframes "on the rails" do not change unless absolutely necessary (and many times not even then).


You can also argue that debugging time can be expensive but static checks reduce debugging. This is much more true when it's concurrency errors.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: