5 ms·
>You can compose things without a type system Compose an array of strings with an integer. What do you get? Run time error OR type error. Please don't make up
by crimsonalucard 7y ago
>You can compose things without a type system
Compose an array of strings with an integer. What do you get? Run time error OR type error. Please don't make up an arbitrary definition of composition as a counter example. These things generally don't compose unless you make up some definition on the spot.
>You just have to take care to make sure the result makes sense in your domain (which a type system helps automate for you).
Thanks for retelling me what I've been telling you since the beginning.
> That's exactly what the previous OO example did, but you complained that being able to compose anything somehow doesn't count as composition because it's not restrictive enough. Now you're complaining that not being able to compose anything somehow doesn't count as composition.
You don't get it. It should compose anything under a single rule of composition WITH CONTEXT. You are defining an arbitrary compose for a specific pair of types that keeps context but this definition of composition will fail with every other instance of any primitive outside of the Foo and Bar type.
>Let's dig into what you might mean by that, though - specifically with your "arbitrary composition rule for addition". How would you go about implementing add(Store, Chicken) (or Store + Chicken)? What would that mean? What would your THREE actually be after adding your ONE and TWO?
You're asking me? LOL. I'm actually the one asking YOU. I'm telling you that it's NOT POSSIBLE to compose things this way for objects and procedures. you're claiming it is.
Let me state this as specifically as possible. Compose two THINGS under a universal DEFINITION with correct CONTEXT is what I'm talking about. Meaning a function that can compose cooking and ingredients into food can also compose eggs and sugar into a cookie while maintaining knowledge about what a cookie is, and what food is.
Additionally, I am SAYING such a compose function for objects or procedures as parameters with OR without a type system CANNOT BE done.
>but it seems like you ain't exactly satisfied by that answer. Unfortunately, the type system alone doesn't really help you much here; just because the computer knows what a Chicken and a Store and a Popeyes is doesn't mean it knows how to add a Chicken and a Store to get a Popeyes.
Yeah I'm not satisfied with your answers. I'm satisfied with A answer that you don't currently know about. It is definitely possible to compose two primitives with context and with no mortar or rebar under a universal compose function. Just not with objects or procedures as primitives.
>If you object to the "nonsensical" results of trying to add a Store to a Chicken, then you can't get around having to define specific implementations of that composition between a Store and a Chicken. Maybe you can cheat through it a bit by subclassing them from a common ancestor or having them both implement an interface and then add against that ancestor/interface, but that just punts the problem
The problem isn't adding these things together. It's impossible to add these things together. It's getting your computer to know what can be composed and what can't. Your computer should know that composing a chicken with a store doesn't make sense. Either way you're starting to see the full picture because it doesn't even make sense to compose two chickens without you making up an arbitrary definition.
There is ONE primitive where you can do this type of composition. It also relies on parametric polymorphism so in general you can't compose all these primitives together, only primitives of relevant context. Primitives of relevant contexts will compose to form higher order abstractions with contexts that make sense under a SINGLE definition.
If you build your entire program using nothing but composing this primitive then every atom of your program is legos. Modular, reusable, refactorable, scalable. Powerful.
- yellowapple 7y ago> You are defining an arbitrary compose for a specific pair of types that keeps context but this definition of composition will fail with every other instance of any primitive outside of the Foo and Bar type. Well guess what? That's what's necessary to compose things. That's what your compiler or interpreter is doing behind the scenes. You cannot escape this. And yes, "things" includes functions (the "primitive" you seem so averse to actually naming for some reason). It might surprise you to learn that "functions" and "procedures" are literally the same thing as far as the computer's concerned (at most, a "function" might be a procedure plus type information, or it might be a procedure that does its own type checking, but it's ultimately a procedure nonetheless). When you pass a "function" as an argument, you're literally passing around a pointer to the code that needs executed (whether already compiled or in some not-yet-compiled representation). But as far as the computer knows, it's just yet another machine-width integer; you would have to establish what it means to "compose" two integers. Composing functions is - when all is said and done - literally what my pseudo-Forth example demonstrated, because functions are ultimately just procedures. Forth literally has no type system (at least not by modern standards), and yet it fulfills the literal actual definition of function composition. But no, for some reason that ain't good enough, probably because you seem to believe that there's no middle ground between clean composition (what a type system actually provides) and no composition at all. Put differently: > These things generally don't compose unless you make up some definition on the spot. Nothing composes unless you make up some definition on the spot. Composition is meaningless unless you define what "composed" means in a given context. For functions, they're "composed" by calling one with the other's output. For procedures, they're "composed" by calling them one after the other. For objects, they're "composed" typically by either aggregation or inheritance/delegation. > If you build your entire program using nothing but composing this primitive Not even the purest of functional languages can truly do that. Ultimately, they rely on actual primitives for data; it ain't functions all the way down. Even purely-mathematical functions need numbers to, um, func. The closest you can get to that is... (drumroll...) Forth, which treats any word it doesn't recognize as a call to an imaginary procedure that pushes the value of that word onto the stack, thus trying its darndest to make everything pretend to be a procedure (and thus composable as such). Unsurprisingly - because functions are just fancy procedures - this concept has worked its way into the functional programming realm through concatenative programming. Put differently: the "power" you feel when clicking together functions like Lego bricks is possible specifically because of procedural composition; the former is just syntax sugar around the latter.