title: Ocaml match fails
body: <pre><code>type ide = string;;
  type integer = int;;
  
  (*Eccezioni*)
  exception WrongMatchException;;
  exception EmptyEnvException;;
  exception TypeErrorException;;
  exception UnboundRecordException;;
  exception OutOfBoundException;;
  
  type exp =
      | Ide of ide (*Identificatore*)
      | Int of int (*Valori Interi*)
      | Bool of bool (*Valori Booleani, true=1, false=0*)
      | Add of exp * exp (*Operatori Matematici*)
      | Sub of exp * exp
      | Mul of exp * exp
      | Eq of exp * exp
      | Leq of exp * exp
      | And of exp * exp (*Operatori Logici*)
      | Or of exp * exp
      | Not of exp
      | Function of ide * ide * exp (*Funzione con un parametro, non ricorsiva*)
      | IfThenElse of exp * exp * exp (*Classico If Then Else *)
      | LetIn of ide * exp * exp (*Blocco Let*)
      | FunApply of ide * exp (*Applicazione funzionale Ide(E)*)
      | Tupla of ide * elts (*Espressione Tupla*)
      | GetIndex of elts * exp (*Accesso Elemento Tupla*)
      | GetFirstN of elts * exp (* Seleziona elementi Tupla*)
      | TupleEquals of elts * elts (*Confronto tra tuple*)
      | Map of ide * exp (*Applica funzione ad elementi tupla*)
      | ListaE of elts
  and
  (*Elementi di una tupla*)
      elts = Elemento of exp | Lista of exp list
  ;;
  
      (* the empty environment *)
      (* emptyEnv: 'a -&gt; 'b *)
  let emptyEnv = fun x -&gt; raise EmptyEnvException;;
  let emptyFunEnv = fun x -&gt; raise EmptyEnvException;;
  let emptyTuplaEnv = fun x -&gt; raise EmptyEnvException;;
      (*bind: ('a -&gt; 'b) -&gt; ide -&gt; exp -&gt; (ide -&gt; exp ) *)
  let bind env (variable: ide) value = fun y -&gt;
              if variable = y then value else env y;;
  
      (*Funzioni di supporto*)
  (*Casting da exp a tipi primitivi*)
  let asint = function Int x -&gt; x | _ -&gt; failwith "not an integer";;
  let asbool = function Bool x -&gt; x | _ -&gt; failwith "not a boolean";;
  let aslist = function Lista x -&gt; x | _ -&gt; failwith "not a list";;
  (*Cast da Lista_exp to Lista_elts *)
  let aslist_e = function ListaE x -&gt; x | _ -&gt; failwith "not a list_e";;
  let tupla2Lista = function Tupla(x, y) -&gt; y | _ -&gt; failwith "non a tupla";;
  
  let rec getElement lista index = match lista with
      | [] -&gt; raise OutOfBoundException
      | primo::elems -&gt; if index = 0 then primo else getElement elems (index-1);;
  
  let rec first lista number = if number = 0 then [] else
      let lista1 = aslist(lista) in
          match lista1 with
          | [] -&gt; raise OutOfBoundException
          | primo::elems -&gt; let resto = Lista(elems) in primo::(first resto (number-1));;
  
  let rec map lista funct = match lista with
      | [] -&gt; []
      | elem::elems -&gt; (funct elem)::(map elems funct);;
  
  let rec valTuple lista eval_fun env funenv tenv = match lista with
      | [] -&gt; []
      | elem::elems -&gt; (eval_fun elem env funenv tenv)::(valTuple elems eval_fun env funenv tenv);;
  
  let funDeclr (expression: exp) env funenv = match expression with
      | Function (funName, param, body) -&gt; bind funenv funName (param, body, env)
      | _ -&gt; raise WrongMatchException;;
  
  let tupleDeclr (tupla: exp) env tenv = match tupla with
      | Tupla (id, lista) -&gt; bind tenv id lista
      | _ -&gt; raise WrongMatchException;;
  
  let append elemento lista2 = let lista21 = aslist (aslist_e lista2)
                                  in elemento::lista21
  
  let appendE elemExp elemExpLE = let listaE = aslist_e elemExpLE in
                                  match listaE with
                                  | Elemento (expr) -&gt; Lista(elemExp::[expr])
                                  | Lista (exprlist) -&gt; Lista(elemExp::exprlist);;
  
  let rec eval (expression: exp) env funenv tenv =
      match expression with
      | Int i -&gt; Int(i)
      | Ide i -&gt; env i
      | Bool i -&gt; Bool(i)
      | Add (e1, e2) -&gt; Int(asint(eval e1 env funenv tenv) + asint(eval e2 env funenv tenv))
      | Sub (e1, e2) -&gt; Int(asint(eval e1 env funenv tenv) - asint(eval e2 env funenv tenv))
      | Mul (e1, e2) -&gt; Int(asint(eval e1 env funenv tenv) * asint(eval e2 env funenv tenv))
      | Eq (e1, e2) -&gt; if (eval e1 env funenv tenv) = (eval e2 env funenv tenv) then Bool(true) else Bool(false)
      | Leq (e1, e2) -&gt; if (eval e1 env funenv tenv) &lt;= (eval e2 env funenv tenv) then Bool(true) else Bool(false)
      | And (e1, e2) -&gt; if asbool(eval e1 env funenv tenv) &amp;&amp; asbool(eval e2 env funenv tenv) then Bool(true) else Bool(false)
      | Or (e1, e2) -&gt; if asbool(eval e1 env funenv tenv) || asbool(eval e2 env funenv tenv) then Bool(true) else Bool(false)
      | Not (e1) -&gt; if asbool(eval e1 env funenv tenv) then Bool(false) else Bool(true)
      | FunApply (funName, arg) -&gt; (*Chiamata di funzione*)
          let value = eval arg env funenv tenv in
                  let (param, body, ambiente) = funenv funName in
                          let env1 = bind env param value in
                              eval body env1 funenv tenv
      | IfThenElse (e1, e2, e3) -&gt; if asbool(eval e1 env funenv tenv) then eval e2 env funenv tenv
                                                                  else eval e3 env funenv tenv
      | LetIn (id, value, body) -&gt; let value = eval value env funenv tenv in
                                      let env1 = bind env id value in
                                          eval body env1 funenv tenv
      (*| Tupla (id, lista) -&gt; let lista1 = aslist(lista) in
                              let lista0 = valTuple lista1 eval env funenv tenv in
                                      ListaE(Lista(lista0))*)
      | GetIndex (id, i) -&gt; let index = asint(eval i env funenv tenv) in
                              let lista = aslist(id) in
                                  getElement lista index
      | GetFirstN (exp, i) -&gt; let index = asint(eval i env funenv tenv) in
                                  ListaE(Lista(first exp index))
      | TupleEquals (exp1, exp2) -&gt; if aslist(exp1) = aslist(exp2) then Bool(true) else Bool(false)
      | Map (funx, exp1) -&gt; let lista = aslist(aslist_e(eval exp1 env funenv tenv)) in
                           let (param, body, ambiente) = funenv funx in
                          (match lista with
                            | [] -&gt; ListaE(Lista([]))
                            | x::xs -&gt;
                              let value = eval x env funenv tenv in
                                  let env1 = bind env param value in
                                      let remaining = ListaE(Lista(xs)) in
                                          ListaE(appendE (eval body env1 funenv tenv)
                                                  (eval (Map (funx,remaining)) env1 funenv tenv))
                          )
  
      | _ -&gt; raise WrongMatchException
  ;;
  
  (**TEST**)
  let simpleAnd = And(Bool true, Bool true);;
  let doubleAnd = And(Bool true, And( Bool true, Bool false));;
  eval simpleAnd emptyEnv emptyFunEnv emptyTuplaEnv;;
  eval doubleAnd emptyEnv emptyFunEnv emptyTuplaEnv;;
  
  let letAndEquals = LetIn("x", Int 1, Eq(Ide "x", Int 1));;
  eval letAndEquals emptyEnv emptyFunEnv emptyTuplaEnv;;
  
  let simpleAdd = LetIn("x", Int 2, LetIn("y", Int 4, Add(Ide "x", Ide "y")));;
  eval simpleAdd emptyEnv emptyFunEnv emptyTuplaEnv;;
  
  (*Valutazione Tupla*)
  let lista_x = Lista(Ide "x" :: Int(23) :: Add(Ide "x", Int 2) ::[]);;
  let exampleList = LetIn("x", Int 2, Tupla("lista", lista_x));;
  
  eval exampleList emptyEnv emptyFunEnv emptyTuplaEnv;;
  
  (*First 2 elems from tuple*)
  let tupla = Tupla("tupla_x", Lista(Int (5) :: Int(6) :: Bool(true) :: Int(7) ::[]));;
  let primi2 = GetFirstN(tupla2Lista(tupla), Int(2));;
  eval primi2 emptyEnv emptyFunEnv emptyTuplaEnv;;
  
  (*Map(raddoppia, tupla)*)
  let raddoppia = Function("mul2", "x", Mul(Ide "x", Int 2));;
  let funenv0 = funDeclr raddoppia emptyEnv emptyFunEnv;;
  let tupla = Tupla("tupla_x", Lista(Int (5) :: Int(6) :: Bool(true) :: Int(7) ::[]));;
  let lista = tupla2Lista(tupla);;
  let exampleMap = Map("mul2", GetFirstN(lista, Int 2));;
  eval exampleMap emptyEnv funenv0 emptyTuplaEnv;;
  
  (*
  let simpleFunction = LetIn("x", Int 14, FunApply("mul2", Ide "x"));;
  eval simpleFunction emptyEnv funenv0;;
  
  let lista_x = Tuple("lista_x", Lista(Int 4, Int 5, Int 6));;
  let simpleMap = Map("mul2", Ide "lista_x");;
  eval simpleMap emptyEnv funenv0;;
  
  (**TEST DAL PDF**)
  let add5 = Function("add5", "x", Add(Ide "x", Int 5));;
  let funenv1 = funDeclr add5 emptyEnv emptyFunEnv;;
  
  (*let tupla = Tupla(Int 5, Int 6, Bool true, Int 7);;
  let test1 = LetIn("x", Int 5, LetIn("t", tupla, Map(GetFirstN(Ide "t", Int 2)), Function("x", Add(Ide "x", Int 5))));;
  eval test1 emptyEnv funenv1;;*)
  
  *)
  </code></pre>
  
  <p>I'm trying to build an interpreter. Given the following code, when I try to execute its, last line (eval exampleMap emptyEnv funenv0 emptyTuplaEnv;;) returns WrongMatchException. I think that problem is generated by Map, since primi2 use function GetFirstN without any problems.</p>
  
  <p>I don't understand why Map isn't matched. Any ideas?</p>