Live data from Hacker News

What Color Is Your Function?

journal.stuffwithstuff.com

141–150 of 153 posts

Re: What Color Is Your Function?

#141
post #125
post #123

Earlier quoted context omitted.

> Effect Typing and Monads are yet another colour for the lipstick you put on the pig. When I started to read the essay, I thought that it would be an anti-typing screed (it's nothing to do with the author, whom I don't know!), with blue functions being untyped (or, pace Harper, unityped) and red functions being typed. An untyped function can call a typed function by ignoring the types; a typed function cannot call a…

Actually, you can call both ways - from statically typed to dynamically typed and back. This is the premise of the work done in Racket on contracts, and more generally of the "gradual typing" movement. Harper's "unityped" term suggests exactly how this can work. An untyped function takes arguments that are all of one type, and returns one of the same type (that type being the "dynamic" type that includes every possib…

> To call an untyped function from typed code, simply cast all your arguments to this type (trivial, since it contains anything), and check its return value has the type you expect (throwing an error if it's of the wrong type).

To me, as soon as a function includes dynamic checks, it ceases to be statically typed; so I would say that a function that operates this way becomes only dynamically typed.

Re: What Color Is Your Function?

#142
post #141
post #125

Earlier quoted context omitted.

Actually, you can call both ways - from statically typed to dynamically typed and back. This is the premise of the work done in Racket on contracts, and more generally of the "gradual typing" movement. Harper's "unityped" term suggests exactly how this can work. An untyped function takes arguments that are all of one type, and returns one of the same type (that type being the "dynamic" type that includes every possib…

> To call an untyped function from typed code, simply cast all your arguments to this type (trivial, since it contains anything), and check its return value has the type you expect (throwing an error if it's of the wrong type). To me, as soon as a function includes dynamic checks, it ceases to be statically typed; so I would say that a function that operates this way becomes only dynamically typed.

Do you consider any function which may raise an error to be "dynamically typed", then? (For example, any function which performs an array index; or any function which performs I/O; or, to be absurd, any function which allocates memory (since memory is a finite resource that may run out).) If so, I understand the distinction you're making, but it's a very strong position; most people do not mean that when they say "statically typed". If not, I don't understand the distinction you're making.

Admittedly, gradual typing does not mean that calling into untyped code from typed code is "safe" from runtime type errors (although it is safe in the technical preservation-and-progress sense). But it gives you a partial guarantee: if a type error occurs, you know that the fault does not lie in the typed code. This aids debugging, and helps you port over existing codebases gradually. So it's still quite useful.

Re: What Color Is Your Function?

#143
post #142
post #141

Earlier quoted context omitted.

> To call an untyped function from typed code, simply cast all your arguments to this type (trivial, since it contains anything), and check its return value has the type you expect (throwing an error if it's of the wrong type). To me, as soon as a function includes dynamic checks, it ceases to be statically typed; so I would say that a function that operates this way becomes only dynamically typed.

Do you consider any function which may raise an error to be "dynamically typed", then? (For example, any function which performs an array index; or any function which performs I/O; or, to be absurd, any function which allocates memory (since memory is a finite resource that may run out).) If so, I understand the distinction you're making, but it's a very strong position; most people do not mean that when they say "st…

> Do you consider any function which may raise an error to be "dynamically typed", then? (For example, any function which performs an array index; or any function which performs I/O; or, to be absurd, any function which allocates memory (since memory is a finite resource that may run out).)

That's a good question! Yes, in an idealised sense, I do; but, in practice, I think that I would make an exception for functions where the error comes from the host system, not from the program. (For example, if I were too strict about it, then I would have to disallow even the safest of Haskell functions because it might be executed on a computer whose hard drive is failing.) Thus, I would call Haskell's `head` function dynamically typed.

> Admittedly, gradual typing does not mean that calling into untyped code from typed code is "safe" from runtime type errors (although it is safe in the technical preservation-and-progress sense).

I think that I don't understand the definition. Isn't encountering a runtime error precisely getting 'stuck' (in the "opposite-of-progress" sense)?

Re: What Color Is Your Function?

#144
post #143
post #142

Earlier quoted context omitted.

Do you consider any function which may raise an error to be "dynamically typed", then? (For example, any function which performs an array index; or any function which performs I/O; or, to be absurd, any function which allocates memory (since memory is a finite resource that may run out).) If so, I understand the distinction you're making, but it's a very strong position; most people do not mean that when they say "st…

> Do you consider any function which may raise an error to be "dynamically typed", then? (For example, any function which performs an array index; or any function which performs I/O; or, to be absurd, any function which allocates memory (since memory is a finite resource that may run out).) That's a good question! Yes, in an idealised sense, I do; but, in practice, I think that I would make an exception for functions…

> I think that I don't understand the definition. Isn't encountering a runtime error precisely getting 'stuck' (in the "opposite-of-progress" sense)?

Sorry, perhaps I should have said "exception" rather than "error". Raising an exception is absolutely "safe"/progress-obeying, as long as your language specifies the behavior of exceptions. That the exception happens to be called a "TypeError" doesn't change anything.

Getting "stuck" means being in a state such that there's no defined next state - a state which the language spec doesn't cover. So most "dynamically-typed" languages are in fact safe in progress-and-preservation terms, because they have well-defined behavior in all cases. C, otoh, is "statically-typed" but unsafe, because you can write C code with undefined behavior.

(That dynamically typed languages can be (statically) typesafe should be unsurprising, since they're just statically-unityped languages. Nothing says a unityped language can't be typesafe, it's just a very uninteresting property!)

Re: What Color Is Your Function?

#145
post #43

Earlier quoted context omitted.

Since he's a Go fan, he might prefer lightweight threads running in an event loop rather than real threads with their context-switches. Moreover his concern is syntactic , not semantic: so maybe he'd like something which "looks thread-like" but "complies-to-CPS" too. Some Microsoft engineers are working on a nice solution to the thread-race-condition problem with a somewhat different approach: pretend your threaded e…

If you are interested in concurrent revisions, you might also be interested in Glitch: http://research.microsoft.com/en-us/people/smcdirm/managedti... In contrast to Burckhardt et. al's work, Glitch re-executes computations to reach a fixed point (logging side effects so they can be rolled back along the way). This paper compares the various approaches in solving this problem (including concurrent revisions, but also…

This has been a fascinating read, but I worry that there's too much pressure in the paper to view all of these different approaches as somehow "solving the same problem". I'm not sure they do.

There is this "whoops, my state updated out from under me" concurrency problem. To steal a metaphor from physics, the problem is that we expect the spacetime to be "locally flat" but to curve at long scales -- similarly we expect the state to somehow be locally private but globally we discover it's shared. The multiple timelines (of operations in various threads) contain updates to the shared state which are noncommutative; when we synchronize we try to throw up these big walls, global across all timelines, across which operations cannot pass.

Glitch's approach is to break these threads into commutative-and-noncommutative parts (fixed-points and events). So the focus is not actually on the fixed-points; they can be parallelized without fear because the operations on the state commute. The focus is instead on the events. And there it's not clear that the events solve the concurrency problem at all. (Please don't take that as a criticism; I don't think you were trying to solve this problem. Your approach reminds me a little of Sussman's propagators, and definitely it has some nice implications for live-coding.)

Concurrent revisions are a more direct response. The basic insight is that no matter what, "there is one authoritative timeline, let's call it the consumer-timeline, which is how all of these noncommutative events from multiple timelines will actually be ordered." Given that insight, and the need for the state to look locally-private, these explicit joins are an obvious solution. The joins look a little jarring because in the spacetime analogy we're talking about a 'piecewise-smooth' function, so there's a sort of derivative-discontinuity happening here.

What would be really interesting is if the shared commutative operations of Glitch could change "piecewise smooth" to "smooth", but I don't think these ideas have that power.

Re: What Color Is Your Function?

#146
post #77

Earlier quoted context omitted.

Go's "good, pragmatic engineering" solution to the problem - lightweight threads, channels, and the communicating sequential processes model - is built on the back of decades of academic research, including programming languages research. And now for some computer language geekery: Go solves one "code color" problem (concurrency/asynchrony), by hard-coding the solution into the language. Go programs are written in a…

Indeed, Go only solves one problem by baking it into the language/runtime, it doesn't have a generic mechanism to solve similar problems. But my point is that it solves the problem much better than monads do - in particular if you don't just look at the syntax/user interface level, but at the non-functional aspects, like debuggability, performance, etc. I remember a time when Aspect Oriented Programming was all the r…

"AOP is certainly less generic than monads, but even with rather specialized tools, it turns out the two "killer apps" of AOP were much better served by runtime support in the VM (logging/debugging) and explicit code (transactions)."

Indeed... beware the tech promoted with the same example over and over again. That's a huge red flag.

Re: What Color Is Your Function?

#147
post #39
post #35

Earlier quoted context omitted.

I think the point is that there is no good effect-union type; this has to be pieced together with monad transformers where you might have that types "Atransformer (Btransformer C)" is not equal to "Btransformer (Atransformer C)". This is, for example, why Haskell has one monolithic "IO" monad instead of one for hitting the filesystem, one for HTTP requests, one for IORefs, etc. Haskell does not, for example, represen…

I know there are a lot of solutions to this, but I've personally found the `mtl` mechanism in Haskell to be completely sufficient. I describe whatever effect languages I want my application bits to be able to operate over as separate type classes and then build one or more interpreters of these classes to run. Essentially it's mtl + Oleg's "Finally Tagless" mechanism [0] [1]. The problem with this mechanism is not fe…

It took me a while to start to grok the "Finally Tagless" thing; thanks for that!

Re: What Color Is Your Function?

#148
post #96
post #54

So I've been writing javascript full time for a couple years at this point, client, server, and open source, and what I have adopted is coercing everything into promises, which I suppose would be the author's way of saying making everything red. If you have something that is not async mixed in with something that's async, you can still add it to the promise chain and it will resolve right away. If you have a library…

This is great for one's own projects, but if creating something for more than one's immediate project (i.e. libraries), it forces everyone else to adopt the same style. Maybe those other projects are also using other libraries that don't use promises, so now there is a problem. Do you wrap the other library in promises too, if that is even a viable option for you? Colorness is a problem for the whole ecosystem too.

Maybe I didn't get this across in my original comment, but my primary job is open source software. So I spend ~40h/week working on public projects that are not all my own. I spend tons of time contributing to other peoples' projects, and I authored and maintain a significant number of libraries that are used by other developers.

What I was saying is that it does work. I can use dependencies with no problems no matter what they expose by coercing to promises internally, and have had no complaints about my libraries' APIs use of promises.

Re: What Color Is Your Function?

#149
post #125
post #123

Earlier quoted context omitted.

> Effect Typing and Monads are yet another colour for the lipstick you put on the pig. When I started to read the essay, I thought that it would be an anti-typing screed (it's nothing to do with the author, whom I don't know!), with blue functions being untyped (or, pace Harper, unityped) and red functions being typed. An untyped function can call a typed function by ignoring the types; a typed function cannot call a…

Actually, you can call both ways - from statically typed to dynamically typed and back. This is the premise of the work done in Racket on contracts, and more generally of the "gradual typing" movement. Harper's "unityped" term suggests exactly how this can work. An untyped function takes arguments that are all of one type, and returns one of the same type (that type being the "dynamic" type that includes every possib…

(Late to the party; sorry)

> you can't dynamically check something of a function type

Another approach, besides contracts, (one that my lab is working on) relies on whole program type-checking and path-sensitive program analysis.

Re: What Color Is Your Function?

#150
post #84
post #76

Earlier quoted context omitted.

Go seems to have solved the IO problem, but what about the general asynchronous issue? How do you handle calling a function several thousand times on dozens of threads and combine the results?

How does Go solve "the IO problem"? (Probably what I want to ask is: which IO problem does Go solve? It can't be the one about purity and side-effects, and if it doesn't solve that...)

How do you do IO without stalling your whole program while it accesses the data, specifically the fact that the asynchronous call is terminated in your main loop, not where you are accessing the IO itself.
Post reply on HN