4

First question here and just want to preface that I did several queries and while I found multiple questions that were worded similarly I found none that were asking, or answering, the question I have (as far as I can tell).

I'm working in SML on an assignment for class so I'm going to leave some details out so I can resolve the issue myself. I have the following type defined in SML:

- type Env = string -> int;

Essentially, the Env type is supposed to be a function that allows mapping from a string to an int - it's a simple environment scheme. It is trivial enough to create a function that does this, i.e.:

- fun foo (s:string) = 10; (*simple example*)

But is there a way to actually declare this function as a "Env type"? The reason is eventually I need to create a function whose return value is an Env type function and I have no idea how to perform this. I'm aware SML allows type aliasing and I think this means that technically any function which has the type string -> int would be synonymous with the Env type to the program, but I would like something more explicit.

If clarification is needed please ask and I will attempt to be more concise.

vitaFrui
  • 53
  • 4

3 Answers3

3

The reason is eventually I need to create a function whose return value is an Env type function and I have no idea how to perform this.

When using fun, you can specify that the return-type is Env by putting the type annotation : Env after all of the argument-patterns; for example:

fun fooFactory arg : Env = ...
ruakh
  • 175,680
  • 26
  • 273
  • 307
  • While some of the answers below are insightful and explanatory I appreciate the conciseness of this one. Thank you for your help. – vitaFrui Feb 08 '16 at 17:07
1

You could use a val binding rather than a fun declaration to get SML to explicitly associate the type with the function. Either a two-step process like this:

- fun foo_temp (s:string) = 10;
val foo_temp = fn : string -> int

- val foo:Env = foo_temp;
val foo = fn : Env

Or you could use an anonymous function:

 -val (foo:Env) = fn (s:string) => 10;
val foo = fn : Env

I'm not sure if it is possible to do it directly using the fun keyword. For example, the following fails:

-fun (foo:Env) (s:string) = 10;

with the somewhat cryptic message Error: illegal function symbol in clause

Perhaps there is some other workaround that I am not familiar with

John Coleman
  • 51,337
  • 7
  • 54
  • 119
  • +1. Note that in the `foo_temp` case, you should probably use `local` (and can even use the name `foo`). Also note that in the anonymous-function case, you will need to use `val rec` if the function is recursive. Lastly, note that you could accomplish approximately the same thing by putting `val _ = foo : Env` on the following line. – ruakh Feb 08 '16 at 01:02
1

Since Env is just a type alias (being created using type Env = ... rather than e.g. datatype Env = ... or abstype Env = ...), creating a function that returns an Env is exactly the same as creating a function that returns a string → int function.

Here are two interpretations of your question:

How do I create a function that returns a string → int function?

There are several ways, it really depends on what it should be doing. But some examples could be:

val zero_env = fn s => 0
fun update_env env t x = fn s => if s = t then x else env s
fun add_env env t x = fn s => env s + (if s = t then x else 0)

How do I ensure that the type signature explicitly says ... → Env rather than ... string → int?

  1. Use datatype Env = ...:

    datatype Env = Env of string -> int
    fun unEnv (Env f) = f
    val zero_env = Env (fn s => 0)
    fun update_env env t x = Env (fn s => if s = t then x else (unEnv env) s)
    fun add_env env t x = Env (fn s => (unEnv env) s + (if s = t then x else 0))
    
  2. Use abstype Env = ...:

    abstype Env = Env of string -> int
    with
        (* ... same as e.g. type Env = ..., except now the Env type is opaque ... *)
    end
    
  3. Use modules:

    signature ENV =
    sig
        type Env
        val zero_env : Env
        val update_env : Env -> string -> int -> Env
        val add_env : Env -> string -> int -> Env
        ...
    end
    
    structure FunctionalEnv : ENV =
    struct
        (* ... same as e.g. type Env = ..., except now the Env type is opaque ... *)
    end
    
sshine
  • 15,635
  • 1
  • 41
  • 66