Reputation: 53
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
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?
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))
Use abstype Env = ...
:
abstype Env = Env of string -> int
with
(* ... same as e.g. type Env = ..., except now the Env type is opaque ... *)
end
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
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
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