Appendix F: Structure Auto-Selection

If you've used Lux structures already (with the :: macro), you've probably noticed that you need to use and pass around the specific structures you need every time you want to call some signature's function, or access some constant value.

That can become tiresome if you need to do it all the time, and specially if you come from languages that do method-selection for you automatically.

Object-oriented languages do polymorphism in an easy way, because they link objects to the method table of their associated classes, and when you call a method on an object, the run-time system can figure out where the code that needs to be run lies within the program's memory.

Languages with type-classes, such as Haskell, perform that look-up at compile-time, by using the type-information present in the compilation context to figure out which implementation (or instance) of a type-class is suitable to each particular circumstance.

Lux, on the other hand, forces you to be specific with the structures that you're going to use.

While that gives you a level of power and flexibility you wouldn't otherwise have in other languages, it also introduces the problem that when what you want doesn't warrant that level of power, you have to pay the tax it involves nonetheless.

But, that sounds like a raw deal.

Why do you have to pay for something you're not taking advantage of?

Clearly, there is an asymmetry here.

There is a feature that is most useful in the few instances when you want full power. At any other point, it's a hindrance.

Well... there is an alternative.

The Lux Standard Library includes a module called lux/type/auto, which provides a macro called :::, that serves as an easier-to-use alternative to the :: macro.

What it does is that instead of requiring the structure you want to use, it only requires the name of the function you want to call and the arguments.

Then, at compile-time, it does some type-checking and some look-ups and selects a structure for you that will satisfy those requirements.

That structure can come from the local-var environment, from the definitions in your own module, or even from the exported definitions of the modules you're importing.

That way, you can use :: whenever you need precision and power, and use ::: whenever you're doing more lightweight programming.

Fantastic!

You is how you'd use it:

## Equality for nats
(:: number;Eq<Nat> = x y)
## vs
(::: = x y)
## Equality for lists of nats
(:: (list;Eq<List> number;Eq<Nat>) =
    (list;n.range +0 +9)
    (list;n.range +0 +9))
## vs
(::: =
     (list;n.range +0 +9)
     (list;n.range +0 +9))
## Doing functor mapping
(:: list;Functor<List> map n.inc (list;n.range +0 +9))
## vs
(::: map n.inc (list;n.range +0 +9))

Thanks to structure auto-selection, you don't have to choose between power and ease of use.

Just do a flat-import of the lux/type/auto module, and you'll get the ::: available and ready for action.

results matching ""

    No results matching ""