2

I check other questions on the same error but answers aren't helpful for my problem. For I see no type mis-match!

The error I get is

  Error: operator and operand don't agree [tycon mismatch]
  operator domain: ?.expr list * ?.env
  operand:         expr list * env
  in expression:
    evallist (exprs,ev)

I do not know what is this question mark in type is for or what does it mean! What I can see is that aside from the question mark part, the types are pretty similar. So I really do not get it.

My function is pretty simple

fun evallist(nil, _) = nil
  | evallist (e::exprs, ev) = eval(e,ev):: evallist(exprs,ev)

It recursively evaluate expressions in the environment and creates a list of the result.

It is invoked simply as

vals = evallist(exprs, ev)

Where eval is an expression evaluation function of this type val eval = fn : expr * env -> expr.

Any explanation/ideas on what is the problem? How ?.expr list * ?.env is different than expr list * env?

Thanks you!

This is the minimal code that will reproduce the error.

Updated Code

datatype
   expr = var of string                     
    | num of int                            
    | appfun of expr * expr list          

type env = (string * expr) list         

fun eval (appfun (e, exprs), ev:env) = evallist(exprs, ev)

fun evallist(nil, _) = nil
  | evallist (e::exprs, ev) = 
    let
        val e' = eval(e,ev)
    in
        e':: evallist(exprs,ev)
    end
S. Nabil
  • 319
  • 1
  • 10
  • What is `eval`? Please make this a [mcve]. Also, see this about the question marks: https://stackoverflow.com/q/23619811/4996248 SML/NJ is known for somewhat cryptic error messages – John Coleman Nov 15 '17 at 16:51
  • Thanks @JohnColeman for your help. I updated the question. I did look at this question before I post mine, but I do not see it feasible here since I am not redefining/shadowing any of my variables! I feel it is so silly, I am suspecting that it has to do with the type inference, but I am not sure what is going on. Any ideas? – S. Nabil Nov 15 '17 at 17:12
  • Without seeing more code it is hard to say what is happening. The code that you show seems nonproblematic, hence the problem must involve code that you don't show. Can you give a [mcve]? Note: this isn't automatically a dump of all your code, it should be minimal subject to the constraint that it allows others to reproduce the problem. – John Coleman Nov 15 '17 at 17:17
  • So -- make it *minimal*. Find the simplest definition of `expr` and `eval` which reproduces the problem (e.g. only evaluate `+` with int literals). It is hard to debug code that you can't even see. As the link [mcve] suggests, the effort in making such an example will often lead you to discover the error on your own. When it doesn't, the effort in making such an example will allow others to help you. – John Coleman Nov 15 '17 at 17:45
  • Alright @JohnColeman, here is a minimal, complete and verifiable example that would reproduce the error. :) It was good to isolate it but still I can't see where the problem is. I certainly hope you can! Thank you for all your help! – S. Nabil Nov 15 '17 at 17:54
  • I think the problem could be in the circularity of the definition between `eval` and `evallist`. Is it!? But I don't know how to fix that, because the intuition is that upon hitting an evaluation of a list, each element should be evaluated separately and the result is a list of expressions in itself. – S. Nabil Nov 15 '17 at 18:34
  • The circularity is definitely a problem. Mutual recursion is possible, but it requires the keyword `and` (not to be confused with the logical operator `andalso`). See this: http://www2.imm.dtu.dk/courses/02153/fun/recursion.4.pdf Having said that, perhaps there would be a way to differential between *expression* lists and *evaluation* lists so as to break the mutual recursion. – John Coleman Nov 15 '17 at 19:23
  • That worked! thanks @JohnColeman so much. But still the error is so misleading, I would expect SML to mention something about circularity instead of type mismatch. I was on to a completely different direction.! – S. Nabil Nov 15 '17 at 20:08

1 Answers1

2

Your evallist function returns a list, and so does eval. I can get your example to compile if I add the missing and and use list concatenation @ instead of consing:

datatype
   expr = var of string                     
    | num of int                            
    | appfun of expr * expr list          

type env = (string * expr) list         

fun eval (appfun (e, exprs), ev:env) = evallist(exprs, ev)
and evallist(nil, _) = nil
  | evallist (e::exprs, ev) = 
    let
        val e' = eval(e,ev)
    in
        e' @ evallist(exprs,ev)
    end

But I must admit I have no idea if this is what you want because the example has been reduced too far.

Florian Weimer
  • 32,022
  • 3
  • 48
  • 92