Then, requirements change. You will have characters with multiple weapons! Your type is now [Weapon] (Haskell) or List<Weapon> (Java). You are forced to go through your entire codebase making changes: some trivial, some logic changes.
You would have to make those changes whether you’re using a statically typed language or not. A type checker tells you exactly where those changes have to be made.
At no point in this process can you run the program to see if any of the updated code is correct.
In any statically typed language, code that doesn’t type-check doesn’t constitute a program, and the question of whether a non-program is correct is meaningless. If you want to analyze program fragments individually, that’s what modules are for.
Flattening an arbitrarily nested list.
In Haskell, there are essentially two possibilities:
(0) You have a value of type [[[...a..]]], in which case you know statically how deeply your lists are nested, and thus you know statically how many times you need to flatten it.
Applying an arbitrary length list of functions [a -> b, b -> c, …] to a value of type a.
The only thing you can do with a sequence of type-compatible functions is compose them, so you might as well compose them all instead of explicitly building a list. But, if you insist on using a list, you can use type-aligned sequences: http://hackage.haskell.org/package/type-aligned .
Serialising or deserialising arbitrary values.
How do you serialize functions without breaking equational reasoning? (Pure operations on equal values produce equal rules. Note that function equality is extensional.)
For example, it makes memoisation for arbitrary functions straightforward (I understand it’s possible in Haskell, but it’s extremely non-trivial).
Memoization for functions is easy provided the function’s argument type supports decidable equality testing, and completely impossible otherwise.
One big advantage of providing eval is that it allows you to write an interpreter. In many scripting languages, the users have developed interpreters that are much friendlier and more capable than the built-in one.
Correction: One big advantage of eval is that an interpreter is already provided for you. In many scripting languages, users have developed interpreter front-ends that are…
You would have to make those changes whether you’re using a statically typed language or not. A type checker tells you exactly where those changes have to be made.
It may also tell you about places where you’ve written overly-specific code that should have been generic.
How do you serialize functions without breaking equational reasoning? (Pure operations on equal values produce equal rules. Note that function equality is extensional.)
What’s the issue? A serialized/deserialized function is extensionally equal to the original, no?
Memoization for functions is easy provided the function’s argument type supports decidable equality testing, and completely impossible otherwise.
So maybe the language should make the distinction between functions with or without this property very clear?
This seems to be an unhelpfully contrived example. If a game is changing from zero or one weapons per player to zero or more weapons per player there will be many interesting related changes to the state transitions. e.g. can the player fire all weapons at any time? one weapon at a time? multiple weapons at a time depending on the specific weapons and/or the specific player?
Regardless of the specific language or type system, these kinds of changes to the behavior of the game are best made incrementally, and are the most interesting aspects of programming well.
You would have to make those changes whether you’re using a statically typed language or not. A type checker tells you exactly where those changes have to be made.
In any statically typed language, code that doesn’t type-check doesn’t constitute a program, and the question of whether a non-program is correct is meaningless. If you want to analyze program fragments individually, that’s what modules are for.
In Haskell, there are essentially two possibilities:
(0) You have a value of type
[[[...a..]]], in which case you know statically how deeply your lists are nested, and thus you know statically how many times you need to flatten it.(1) You have a value of type
Free [] a, in which case you justretractit to get a value of type[a]: http://hackage.haskell.org/package/free-4.12.4/docs/Control-Monad-Free.html#v:retract .In either case, no dynamic typing is necessary.
The only thing you can do with a sequence of type-compatible functions is compose them, so you might as well compose them all instead of explicitly building a list. But, if you insist on using a list, you can use type-aligned sequences: http://hackage.haskell.org/package/type-aligned .
How do you serialize functions without breaking equational reasoning? (Pure operations on equal values produce equal rules. Note that function equality is extensional.)
Memoization for functions is easy provided the function’s argument type supports decidable equality testing, and completely impossible otherwise.
Correction: One big advantage of
evalis that an interpreter is already provided for you. In many scripting languages, users have developed interpreter front-ends that are…It may also tell you about places where you’ve written overly-specific code that should have been generic.
What’s the issue? A serialized/deserialized function is extensionally equal to the original, no?
So maybe the language should make the distinction between functions with or without this property very clear?
How do you guarantee that all extensionally equal functions are serialized to the same string? You can’t.
It’s not really a property of the function. It’s a property of the argument type. And most typed languages can express this.
Oops, sorry! I meant equal results.
Type-holes in GHC alleviate some of the pain the author talks about. I haven’t really found any of these things to be really problematic, though.
This seems to be an unhelpfully contrived example. If a game is changing from zero or one weapons per player to zero or more weapons per player there will be many interesting related changes to the state transitions. e.g. can the player fire all weapons at any time? one weapon at a time? multiple weapons at a time depending on the specific weapons and/or the specific player?
Regardless of the specific language or type system, these kinds of changes to the behavior of the game are best made incrementally, and are the most interesting aspects of programming well.