0

I am a beginner of sml and I'm taking programming language courses at Coursera. There's a datatype and function that I don't know how to evaluate:

datatype exp = constant of int
     | Negate of exp
     |Add of exp * exp
     |Multiply of exp * exp

fun true_of_all_constants(f,e) =
    case e of
    constant i => f i
      | Negate e1 => true_of_all_constants(f,e1)                
      | Add(e1,e2) => true_of_all_constants(f,e1)
              andalso true_of_all_constants(f,e2)
      | Multiply(e1,e2) => true_of_all_constants(f,e1)
              andalso true_of_all_constants(f,e2)

Trying to evaluate them, I always get errors:

true_of_all_constants [3,4,5];
true_of_all_constants 4;
true_of_all_constants (is_even 4, 5);

where is_even is a little helper function:

fun is_even v =
(v mod 2 = 0)

To test true_of_all_constants, what should e be replaced with? Also, could you explain what does datatype do here? I don't understand why we need "Negate" or "Add" here; why we have "exp*exp," rather than "exp+exp," for "Add?"

  • "*Trying to evaluate them, I always get errors*" - please show us the code you are trying to evaluate – Bergi May 26 '19 at 19:42
  • "*could you explain what does datatype do here?*" - are you asking what the `datatype` keyword means here, or are you asking what the meaning and purpose of that particular `exp` datatype are? – Bergi May 26 '19 at 19:43
  • @Bergi Updated my op. Please take a look. Thanks! – Vivian Miller May 26 '19 at 20:21
  • 1
    The call should rather look like `true_of_all_constants(is_even, Constant 4)` or `true_of_all_constants(is_even, Add(Negate(Constant 2), Multiply(Constant 3, Constant 4)))` – Bergi May 26 '19 at 20:48
  • @Bergi What does "Add" do in "Add(Negate(Constant 2))?" Would it be (-2)+(-2)=-4? – Vivian Miller May 26 '19 at 23:12
  • 1
    It creates an instance of your datatype. It doesn't compute anything, it creates an abstract representation of such a mathematical expression. – Bergi May 27 '19 at 05:13

1 Answers1

1

Fixing whitespace, the data type definition and the definition of true_of_all_constants (p, e) become:

datatype exp =
    Constant of int
  | Negate of exp
  | Add of exp * exp
  | Multiply of exp * exp

fun true_of_all_constants (p, e) =
    let fun aux (Constant i)        = p i
          | aux (Negate e1)         = aux e1
          | aux (Add (e1, e2))      = aux e1 andalso aux e2
          | aux (Multiply (e1, e2)) = aux e1 andalso aux e2
    in aux e end

Here constant has been renamed to Constant: Both will work, but naming constructors with an uppercase letter differentiates it visually from other identifiers. And I've used an inner function, aux, to shorten the recursive expressions a bit. Instead of f I called it p for predicate, but that's a taste thing.

Trying to evaluate them, I always get errors

Here are some examples of expressions and evaluating them:

- val two_plus_two = Add (Constant 2, Constant 2);
- true_of_all_constants (fn i => i = 2, two_plus_two);
> val it = true : bool

- val two_times_neg_two = Multiply (Constant 2, Constant ~2);
- true_of_all_constants (fn i => i > 0, two_times_neg_two);
> val it = false : bool

- val two_four_six = Add (Constant 2, Add (Constant 4, Constant 6));
- fun is_even x = x mod 2 = 0;
- true_of_all_constants (is_even, two_four_six);
> val it = true : bool

could you explain what does datatype do here?

I think you should refer to a book or tutorial here.

For example, ML for the Working Programmer, ch. 4 (free PDF) deals with datatype definitions.

I don't understand why we need "Negate" or "Add" here

I don't know, either. The problem you're given in the course is entirely hypothetical.

sshine
  • 15,635
  • 1
  • 41
  • 66