vitaFrui
vitaFrui

Reputation: 53

(SML) Defining a type as a function and creating a function of this type

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.

Upvotes: 4

Views: 675

Answers (3)

sshine
sshine

Reputation: 16105

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
    

Upvotes: 1

ruakh
ruakh

Reputation: 183240

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 = ...

Upvotes: 3

John Coleman
John Coleman

Reputation: 51998

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

Upvotes: 1

Related Questions