Search code examples
smlmlhigher-order-functions

Higher-order functions homework in SML


I'm having trouble writing a function that will take a list of functions and an argument, then call each function with the passed argument, returning a list of the results of the calls. Example: build [f, g, h] 2 would return this, but with the functions called and the results instead of the call: [f(2), g(2), h(2)] Using SML/NJ, by the way.

First I tried many variants of this pattern:

fun build functions TheArgument = if functions = [] then [] else
    [hd(functions) TheArgument] @ build tl(functions) TheArgument;

But it gave the following error:

stdIn:2.9-2.36 Error: operator is not a function [equality type required]
  operator: ''Z
  in expression:
    (hd functions) TheArgument
stdIn:1.10-2.70 Error: case object and rules don't agree [tycon mismatch]
  rule domain: ''Z list * 'Y
  object: ('X list -> 'X list) * 'W
  in expression:
    (case (arg,arg)
      of (functions,TheArgument) =>
           if functions = nil then nil else (<exp> :: <exp>) @ <exp> <exp>)

Finally, I gave up and tried to do some research. I found the following question: Higher Order Functions in SML/NJ

I tried redefining it as this:

fun build [] argument = []
|   build f::rest argument = [f(argument)] @ build rest argument;

But then the compiler spits this:

stdIn:2.14-2.16 Error: infix operator "::" used without "op" in fun dec
stdIn:1.10-2.67 Error: clauses don't all have same number of patterns
stdIn:2.14-2.16 Error: data constructor :: used without argument in pattern
stdIn:1.10-2.67 Error: types of rules don't agree [tycon mismatch]
  earlier rule(s): 'Z list * 'Y -> 'X list
  this rule: ('W -> 'V) * 'U * 'T * 'W -> 'V list
  in rule:
    (f,_,rest,argument) => (f argument :: nil) @ (build rest) argument

What am I doing wrong?

I'm at a serious loss here, I can deal with cryptic Java/C error messages, but this is just too alien to me.

p.s.: The function cannot be called via build(functions, argument), it NEEDS to be two arguments and not a tuple of 2 arguments.


Solution

  • One simple solution would be to use the standard higher-order function map:

    fun build functions arg = map (fn f => f arg) functions;