Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to import from another file in SML, with a path relative to the importer?

Tags:

sml

smlnj

I'm using SML/NJ, and I need to use a set of functions that are in a certain file f1.sml inside another file f2.sml.

However, I'm not running f2.sml directly, rather, I'm importing it from somewhere else.

If I use the use command in f2.sml with the path to f1.sml relative to f2.sml perspective, by the time I import f2.sml, it will look for the supplied path from the running script perspective.

I cannot use absolute paths, and I'd like not to merge the two files contents.

Sorry if this is a trivial application of the language, but I'm new to SML, and couldn't find the answer yet.

like image 516
leolovesai Avatar asked May 30 '18 01:05

leolovesai


1 Answers

I recommend using SML/NJ's Compilation Manager (CM). It's a build system for SML code in the context of SML/NJ. It can get quite complicated if you need more advanced features, but it's easy to get started. I'll show you a barebones structure and you can adjust as needed. It already comes installed with SML/NJ, so there's no installation process.

I'll use the following directory structure for this example (the file extensions are not imposed, just a convention):

.
├── build.cm
└── src
    ├── foo.fun
    ├── foo.sig
    └── main.sml

build.cm

group
  (* CM allows you to selectively export defined modules (structures,
     signatures and functors) by listing them here. It's useful for
     libraries. *)

  source (-)       (* export all defined modules *)

  structure Main   (* OR, export selectively *)
  signature FOO
  functor Foo
is
  (* Import the SML standard library, aka Basis.  *)
  (* See: http://sml-family.org/Basis/ *)
  $/basis.cm

  (* Import the SML/NJ library *)
  (* Provides extra data structures and algorithms. *)
  (* See: https://www.smlnj.org/doc/smlnj-lib/Manual/toc.html *)
  $/smlnj-lib.cm

  (* List each source file you want to be considered for compilation. *)
  src/main.sml
  src/foo.sig
  src/foo.fun

src/main.sml

structure Main =
  struct
    (* You don't have to import the `Foo` functor. *)
    (* It's been done in build.cm already. *)
    structure F = Foo()

    fun main () =
      print (F.message ^ "\n")
  end

src/foo.sig

signature FOO =
  sig
    val message : string
  end

src/foo.fun

(* You don't have to import the `FOO` signature. *)
(* It's been done in build.cm already. *)
functor Foo() : FOO =
  struct
    val message = "Hello, World!"
  end

Usage

Having the structure in place, you can start compiling using CM.make and running by calling whatever functions you've defined:

$ sml
Standard ML of New Jersey v110.82 [built: Tue Jan  9 20:54:02 2018]
- CM.make "build.cm";
val it = true : bool
-
- Main.main ();
Hello, World!
val it = () : unit
like image 103
Ionuț G. Stan Avatar answered Nov 09 '22 10:11

Ionuț G. Stan