Search code examples
functionfunctional-programmingsmlhigher-order-functions

How to evaluate datatype and true_of_all_constants functions?


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?"


Solution

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