3.4. Writing code that is not tied to a language
Sourcing C++ works, but it pins these conversions to C++. Anyone who wants them from Python has to make a foreign call for arithmetic. Morloc lets you write the definition once, in no language at all:
module unitsAbstract (cels2fahr, meters2feet)
import root
--' Convert from Celsius to Fahrenheit
cels2fahr cels = 1.8 * cels + 32.0
--' Convert from meters to feet
meters2feet meters = meters * 3.28084
root is a language-independent module from the standard library. It declares
the typeclasses for arithmetic and much else, but supplies no
implementations. So + and * here are general operations with no code
behind them yet.
This is the first module the manual imports, and you do not have to install it.
morloc make fetches any missing import, and that module’s own imports, before
it builds:
$ morloc make units-abstract.loc
Auto-installing missing dependency: root
Fetching module 'root'...
Fetching module 'internal'...
Installed module 'internal'
Installed module 'root'
units-abstract.loc:6:29: error:
No implementation found for '+'
|
6 | cels2fahr cels = 1.8 * cels + 32.0
| ^
The install worked. The build did not, and that error is worth sitting with, because it is the shape of Morloc’s central idea.
Nothing is wrong with the module. Now that root is on disk you can ask the
compiler directly, and it types both terms without complaint:
$ morloc typecheck units-abstract.loc
cels2fahr :: Real -> Real
meters2feet :: Real -> Real
|
|
Only the build commands fetch, which is why this section built before it
typechecked. |
So the module is complete as a specification and empty as a program: there is nothing wrong to fix, there is only code missing. To get a program, import a module that carries implementations:
module convert (cels2fahr, meters2feet)
import .units-abstract
import root-cpp
The leading . in .units-abstract marks a local file rather than an installed
module. root-cpp holds the C++ implementations of `root’s terms — here,
just the arithmetic operators.
$ morloc make convert.loc
$ ./convert cels2fahr 100
212
Same answer as the sourced-C++ version, from a definition that never mentioned C++. The build directory says which language it ended up in:
$ ls convert-build/pools/
cpp
And that is the one line you change. Edit convert.loc to import root-py,
rebuild, and the same abstract module compiles to Python:
$ ls convert-build/pools/
py
$ ./convert cels2fahr 100
212
You can import both and let the compiler decide which implementations to use. How it chooses is One term may have many definitions.